ZaiZai 1 éve
szülő
commit
9dded6b3e1

+ 8 - 3
electron.vite.config.mjs

@@ -15,12 +15,17 @@ export default defineConfig({
             alias: {
                 '~src': resolve('src/renderer/src'),
                 '~api': resolve('src/renderer/src/api/modules'),
-                '~ass': resolve('src/renderer/src/assets'),
-                '@renderer': resolve('src/renderer/src')
+                '~ass': resolve('src/renderer/src/assets')
             }
         },
         plugins: [
-            vue(),
+            vue({
+                template: {
+                    compilerOptions: {
+                        isCustomElement: (tag) => tag === 'webview',
+                    }
+                }
+            }),
             UnoCSS(),
         ]
     }

+ 4 - 2
src/main/index.js

@@ -8,7 +8,7 @@ import icon from '../../resources/icon.png?asset'
 //菜单设置
 const menu = Menu.buildFromTemplate([
     {
-        label:  app.name,
+        label: app.name,
         submenu: [
             {
                 label: '关于' + app.name,
@@ -21,7 +21,8 @@ const menu = Menu.buildFromTemplate([
             { label: '强制刷新', role: 'forceReload' },
             { type: 'separator' },
             { label: '退出' + app.name, role: 'quit' },
-        ] },
+        ],
+    },
     {
         label: '编辑',
         submenu: [
@@ -50,6 +51,7 @@ function createWindow() {
         webPreferences: {
             preload: join(__dirname, '../preload/index.js'),
             sandbox: false,
+            webviewTag: true,
         },
     })
 

+ 6 - 6
src/renderer/index.html

@@ -1,12 +1,12 @@
 <!doctype html>
 <html>
-  <head>
+<head>
     <meta charset="UTF-8" />
     <title>档案</title>
     <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:" />
-  </head>
-  <body>
-    <div id="app"></div>
-    <script type="module" src="/src/main.js"></script>
-  </body>
+</head>
+<body>
+<div id="app"></div>
+<script type="module" src="/src/main.js"></script>
+</body>
 </html>

+ 124 - 0
src/renderer/src/components/query/file-pdf.vue

@@ -0,0 +1,124 @@
+<template>
+    <hc-new-card title="pdf文件预览" class="hc-query-file-pdf-card">
+        <template #extra>
+            <div class="file-pdf-close" @click="drawerCloseClick">
+                <i class="i-iconoir-xmark-circle" />
+            </div>
+        </template>
+        <div class="hc-flex relative h-full">
+            <div class="relative h-full flex-1">
+                <webview :src="pdfFileUrl" class="h-full w-full" />
+            </div>
+            <div class="ml-1 h-full w-[200px]">
+                <hc-table ref="tableRef" :column="tableColumn" :datas="tableData" :is-index="false" is-new is-current-row>
+                    <template #title="{ row }">
+                        <el-link type="primary" :underline="false" @click="tableRowTitle(row)">{{ row?.title }}</el-link>
+                    </template>
+                </hc-table>
+            </div>
+        </div>
+    </hc-new-card>
+</template>
+
+<script setup>
+import { onMounted, ref, watch } from 'vue'
+import { useAppStore } from '~src/store'
+import { isNullES } from 'js-fast-way'
+import { exists_file } from '../../utils/tools'
+
+const props = defineProps({
+    datas: {
+        type: Array,
+        default: () => ([]),
+    },
+    rows: {
+        type: Object,
+        default: () => ({}),
+    },
+})
+
+//事件
+const emit = defineEmits(['close'])
+
+//项目信息
+const store = useAppStore()
+const projectInfo = ref(store.projectInfo)
+const dataPath = ref(store.dataPath)
+const projectId = ref('')
+
+//渲染完成
+onMounted(() => {
+    projectInfo.value = store.projectInfo
+    projectId.value = store.projectInfo?.key ?? ''
+    dataPath.value = store.dataPath
+    setRowData()
+})
+
+//监听数据
+const tableData = ref(props.datas)
+const tableRows = ref(props.rows)
+watch(() => [
+    props.datas,
+    props.rows,
+], (data, row) => {
+    tableData.value = data
+    tableRows.value = row
+    setRowData()
+}, { deep: true })
+
+//设置数据
+const isPdfState = ref(0)
+const pdfFileUrl = ref('')
+const setRowData = () => {
+    //初始化数据
+    isPdfState.value = 0
+    pdfFileUrl.value = ''
+    //检测传递参数
+    const row = tableRows.value, data = tableData.value
+    if (isNullES(row.id) || isNullES(row.url) || data.length <= 0) {
+        isPdfState.value = 1 //没有数据
+        return
+    }
+    setPdfPath(row)
+}
+
+//设置PDF路径
+const setPdfPath = (row) => {
+    //检测核心数据
+    const data_path = dataPath.value, pid = projectId.value
+    if (isNullES(data_path) || isNullES(pid)) {
+        isPdfState.value = 2 //数据异常
+        return
+    }
+    //处理pdf文件路径
+    const pdfPath = `${dataPath.value}/${projectId.value}/pdf/${row.url}`
+    //判断pdf文件是否存在
+    if (!exists_file(pdfPath)) {
+        isPdfState.value = 3 //pdf文件不存在
+        return
+    }
+    //pdf文件存在
+    isPdfState.value = 99 //数据正常
+    pdfFileUrl.value = 'file://' + pdfPath
+    //设置当前行
+    tableRef.value?.tableRef?.setCurrentRow(row)
+}
+
+//表格数据
+const tableRef = ref(null)
+const tableColumn = ref([{ key: 'title', name: '卷内文件名称' }])
+
+//表格行被点击
+const tableRowTitle = (row) => {
+    if (row.id === tableRows.value.id) return
+    isPdfState.value = 0
+    pdfFileUrl.value = ''
+    tableRows.value = row
+    setPdfPath(row)
+}
+
+//关闭抽屉
+const drawerCloseClick = () => {
+    emit('close')
+}
+</script>

+ 49 - 3
src/renderer/src/components/query/file-roll.vue

@@ -27,7 +27,8 @@
                 </div>
             </div>
             <div class="relative ml-10">
-                <el-button hc-btn type="info">元数据</el-button>
+                <el-button v-if="tableCheckedKeys.length <= 0" hc-btn type="info" :disabled="tableCheckedKeys.length <= 0">元数据</el-button>
+                <el-button v-else hc-btn type="primary" @click="metaDataClick">元数据</el-button>
             </div>
         </template>
         <hc-table
@@ -39,12 +40,20 @@
             </template>
         </hc-table>
     </hc-new-card>
+    <!-- 元数据 -->
+    <QueryMetaData v-model="isFileMetaData" :ids="metaDataId" :title="metaDataTitle" @close="fileMetaDataClose" />
+    <!-- 预览PDF -->
+    <hc-new-drawer v-model="isFilePdfDrawer" to-id="hc-layout-main" direction="btt">
+        <QueryFilePdf :datas="tableData" :rows="fileRollRow" @close="filePdfDrawerClose" />
+    </hc-new-drawer>
 </template>
 
 <script setup>
-import { onMounted, ref, watch } from 'vue'
+import { nextTick, onMounted, ref, watch } from 'vue'
 import { getArrValue, isNullES } from 'js-fast-way'
 import { sql_table } from '../../utils/dbConnect'
+import QueryFilePdf from './file-pdf.vue'
+import QueryMetaData from './meta-data.vue'
 
 const props = defineProps({
     datas: {
@@ -115,9 +124,46 @@ const tableSelectionChange = (rows) => {
     tableCheckedKeys.value = rows
 }
 
+//元数据
+const isFileMetaData = ref(false)
+const metaDataId = ref('')
+const metaDataTitle = ref('')
+const metaDataClick = () => {
+    const rows = tableCheckedKeys.value
+    if (rows.length <= 0) {
+        window.$message?.warning('请先选择文件')
+        return
+    }
+    if (rows.length > 1) {
+        window.$message?.warning('只能选择一条数据')
+        return
+    }
+    //设置元数据参数
+    metaDataId.value = rows[0].id
+    metaDataTitle.value = rows[0].title
+    nextTick(() => {
+        isFileMetaData.value = true
+    })
+}
+
+//元数据关闭
+const fileMetaDataClose = () => {
+    isFileMetaData.value = false
+    metaDataId.value = ''
+    metaDataTitle.value = ''
+}
+
 //表格行点击
+const isFilePdfDrawer = ref(false)
+const fileRollRow = ref({})
 const tableRowTitle = (row) => {
-    console.log(row)
+    fileRollRow.value = row
+    isFilePdfDrawer.value = true
+}
+
+//关闭预览PDF
+const filePdfDrawerClose = () => {
+    isFilePdfDrawer.value = false
 }
 
 //关闭抽屉

+ 249 - 0
src/renderer/src/components/query/meta-data.vue

@@ -0,0 +1,249 @@
+<template>
+    <hc-new-dialog is-table widths="90%" :footer="false" :show="isShow" :title="`${dataTitle} - 文件元数据`" @close="addModalClose">
+        <table class="hc-csc-meta-table" border="1">
+            <template v-for="(item, index) in metaDataTable" :key="index">
+                <tr v-if="item.type === 2" class="hc-csc-meta-table-tr1">
+                    <td colspan="2" class="hc-csc-meta-table-td">{{ item.title }}</td>
+                </tr>
+                <tr v-else class="hc-csc-meta-table-tr">
+                    <td class="hc-csc-meta-table-td name">{{ item.title }}</td>
+                    <td class="hc-csc-meta-table-td val">{{ item.val }}</td>
+                </tr>
+            </template>
+        </table>
+    </hc-new-dialog>
+</template>
+
+<script setup>
+import { ref, watch } from 'vue'
+import { getArrValue, isNullES } from 'js-fast-way'
+import { sql_find, sql_table } from '../../utils/dbConnect'
+const props = defineProps({
+    ids: {
+        type: [String, Number],
+        default: '',
+    },
+    title: {
+        type: [String, Number],
+        default: '',
+    },
+})
+
+//事件
+const emit = defineEmits(['close'])
+
+//双向绑定
+const isShow = defineModel('modelValue', {
+    default: false,
+})
+
+//监听
+const dataId = ref(props.ids)
+const dataTitle = ref(props.title)
+watch(() => [
+    props.ids,
+    props.title,
+], ([id, title]) => {
+    dataId.value = id
+    dataTitle.value = title
+}, { deep: true })
+
+//监听
+watch(isShow, (val) => {
+    if (val) getTableData()
+})
+
+const metaDataTable = ref([
+    { type: 2, title: '来源', val: '' },
+    { type: 1, title: '全宗名称', val: '/' },
+    { type: 1, title: '立档单位名称', val: '/' },
+    { type: 1, title: '电子文件号', val: '/' },
+    { type: 2, title: '文件联', val: '' },
+    { type: 1, title: '目录文件', val: '/' },
+    { type: 1, title: '文件件数', val: '/' },
+    { type: 1, title: '文件页数', val: '/' },
+    { type: 1, title: '元数据目录文件', val: '/' },
+    { type: 1, title: '验证码', val: '/' },
+    { type: 2, title: '内容描述', val: '' },
+    { type: 1, title: '题名', val: '/' },
+    { type: 1, title: '关键词', val: '/' },
+    { type: 1, title: '摘要', val: '/' },
+    { type: 1, title: '生成方式', val: '/' },
+    { type: 1, title: '责任者', val: '/' },
+    { type: 1, title: '文件创建日期', val: '/' },
+    { type: 2, title: '组件', val: '' },
+    { type: 1, title: 'IP地址', val: '/' },
+    { type: 1, title: '桩号', val: '/' },
+    { type: 1, title: '上传时间', val: '/' },
+    { type: 2, title: '文件标识码', val: '' },
+    { type: 1, title: '文号', val: '/' },
+    { type: 1, title: '表单标识码', val: '/' },
+    { type: 2, title: '竣工图', val: '' },
+    { type: 1, title: '图号', val: '/' },
+    { type: 1, title: '图幅', val: '/' },
+    { type: 1, title: '图表来源', val: '/' },
+    { type: 1, title: '引用变更令编号', val: '/' },
+    { type: 2, title: '照片文件', val: '' },
+    { type: 1, title: '主题', val: '/' },
+    { type: 1, title: '拍摄时间', val: '/' },
+    { type: 1, title: '拍摄地点', val: '/' },
+    { type: 1, title: '摄影者', val: '/' },
+    { type: 1, title: '背景', val: '/' },
+    { type: 1, title: '分组号', val: '/' },
+    { type: 1, title: '组内照片编号', val: '/' },
+    { type: 1, title: '水平分辨率', val: '/' },
+    { type: 1, title: '垂直分辨率', val: '/' },
+    { type: 1, title: '保管期限', val: '/' },
+    { type: 1, title: '格式信息', val: '/' },
+    { type: 2, title: '电子属性', val: '' },
+    { type: 1, title: '位置', val: '/' },
+    { type: 1, title: '计算机文件名', val: '/' },
+    { type: 1, title: '计算机文件大小', val: '/' },
+    { type: 2, title: '数字化属性', val: '' },
+    { type: 1, title: '扫描分辨率', val: '/' },
+    { type: 1, title: '扫描色彩模式', val: '/' },
+    { type: 2, title: '电子签名', val: '' },
+    { type: 1, title: '签名类型', val: '/' },
+    { type: 1, title: '签名时间', val: '/' },
+    { type: 1, title: '签名人', val: '/' },
+    { type: 1, title: '建设项目', val: '/' },
+    { type: 2, title: '业务事项', val: '' },
+    { type: 1, title: '单位工程', val: '/' },
+    { type: 1, title: '分部工程', val: '/' },
+    { type: 1, title: '分项工程', val: '/' },
+    { type: 1, title: '单位工程编码', val: '/' },
+    { type: 1, title: '分部工程编码', val: '/' },
+    { type: 1, title: '分项工程编码', val: '/' },
+    { type: 2, title: '责任者', val: '' },
+    { type: 1, title: '责任者名称', val: '/' },
+    { type: 1, title: '个人职位', val: '/' },
+    { type: 1, title: '责任者手机号', val: '/' },
+    { type: 2, title: '关系实体', val: '' },
+    { type: 1, title: '关系标识', val: '/' },
+    { type: 1, title: '关系类型', val: '/' },
+    { type: 1, title: '关系', val: '/' },
+    { type: 1, title: '相关实体标识', val: '/' },
+])
+
+//获取表格数据
+const tableLoading = ref(false)
+const getTableData = async () => {
+    const id = dataId.value
+    if (isNullES(id)) return
+    //获取文件元数据
+    const { code: code1, data: data1 } = await sql_find(`select * from u_metadata_file where file_id = '${id}'`)
+    const fileData = code1 === 200 ? data1 : {}
+    //获取节点类型
+    const { code: code2, data: data2 } = await sql_find(`select atc.storage_type from u_archive_file uaf left join m_archive_tree_contract atc on uaf.node_id = atc.id where uaf.id = '${id}'`)
+    const storage_type = code2 === 200 ? data2.storage_type : 3
+    let treeType = getStorageType(storage_type)
+    //获取文件字段
+    const { code: code3, data: data3 } = await sql_table('select * from u_metadata_classification')
+    const fieldData = code3 === 200 ? getArrValue(data3) : []
+    //判断是否包含
+    let metadataList = []
+    for (let i = 0; i < fieldData.length; i++) {
+        if (fieldData[i].file_storage_type.indexOf(treeType) !== -1) {
+            // console.log(fieldData[i].code)
+            fieldData[i].keyValue = fileData[fieldData[i].field_key]
+            // console.log(fieldData[i])
+            let r = { title: '', val:'' }
+            r.title = fieldData[i].container_name
+            r.val = fileData[fieldData[i].field_key] ?? '/'
+            if (r.title.indexOf('生成方式') !== -1) {
+                // eslint-disable-next-line eqeqeq
+                if (r.val == 1) {
+                    r.val = '原生'
+                } else {
+                    r.val = '数字化'
+                }
+            }
+            if (r.title.indexOf('密级') !== -1) {
+                // eslint-disable-next-line eqeqeq
+                if (r.val == 1) {
+                    r.val = '机密'
+                    // eslint-disable-next-line eqeqeq
+                } else if (r.val == 2) {
+                    r.val = '绝密'
+                } else {
+                    r.val = '秘密'
+                }
+            }
+            metadataList.push(r)
+        }
+    }
+    //数据存在
+    if (metadataList.length > 0) {
+        metaDataTable.value = metadataList
+    }
+}
+
+//获取节点类型
+const getStorageType = (storage_type) => {
+    let treeType = 'c'
+    if (storage_type == 1) {
+        treeType = 'a'
+    } else if (storage_type == 2) {
+        treeType = 'b'
+    } else if (storage_type == 3) {
+        treeType = 'c'
+    } else if (storage_type == 4) {
+        treeType = 'd'
+    } else if (storage_type == 5) {
+        treeType = 'e'
+    } else if (storage_type == 6) {
+        treeType = 'f'
+    } else if (storage_type == 7) {
+        treeType = 'g'
+    } else if (storage_type == 8) {
+        treeType = 'h'
+    } else if (storage_type == 9) {
+        treeType = 'i'
+    }
+    return treeType
+}
+
+//关闭弹窗
+const addModalClose = () => {
+    isShow.value = false
+    emit('close')
+}
+</script>
+
+<style lang="scss">
+.hc-csc-meta-table {
+    border-spacing: 0;
+    border: 1px solid #F2F2F2;
+    border-collapse: collapse;
+    width: 100%;
+    .hc-csc-meta-table-tr {
+        position: relative;
+        background: white;
+        color: #50545e;
+        transition: background-color .25s ease;
+        &:hover {
+            background: #e6f2ff;
+        }
+    }
+    .hc-csc-meta-table-tr1 {
+        position: relative;
+        color: #1a1a1a;
+        text-align: center;
+        font-weight: bold;
+        background-color: #F4F4F4;
+    }
+    .hc-csc-meta-table-td {
+        text-align: left;
+        padding: 6px 10px;
+        font-size: 13px;
+        border: 1px solid #F2F2F2;
+        &.name {
+            width: 200px;
+            color: #787878;
+        }
+        &.val {
+            color: #787878;
+        }
+    }
+}
+</style>

+ 3 - 1
src/renderer/src/layout/index.vue

@@ -24,7 +24,7 @@
             </div>
         </div>
         <div id="hc-layout-main" class="hc-main">
-            <router-view />
+            <router-view v-if="isMain" />
         </div>
     </div>
 </template>
@@ -48,11 +48,13 @@ watch(() => store.projectInfo, (val) => {
 })
 
 //渲染完成
+const isMain = ref(false)
 onMounted(async () => {
     const { code } = await getProjectInfo()
     if (code !== 200) {
         await router.push({ name: 'project' })
     }
+    isMain.value = true
     setIpcRenderer()
 })
 

+ 18 - 0
src/renderer/src/styles/query.scss

@@ -74,3 +74,21 @@
         }
     }
 }
+
+.el-card.hc-new-card-box.hc-query-file-pdf-card {
+    .file-pdf-close {
+        display: flex;
+        width: 24px;
+        height: 18px;
+        cursor: pointer;
+        z-index: 11;
+        i {
+            font-size: 24px;
+            position: absolute;
+            top: -5px;
+        }
+        &:hover {
+            color: #1890FF;
+        }
+    }
+}

+ 5 - 1
src/renderer/src/utils/dbConnect.js

@@ -64,7 +64,11 @@ export const sql_table = async (sql, path) => {
 
 //单个记录查询
 export const sql_find = async (sql, path) => {
-
+    const { code, data } = await sql_table(sql, path)
+    if (code !== 200 || data.length <= 0) {
+        return { code, data: {} }
+    }
+    return { code, data: data[0] }
 }
 
 //查询统计

+ 2 - 2
src/renderer/src/views/home.vue

@@ -46,7 +46,6 @@ import { filterSize, isNullES } from 'js-fast-way'
 import dayjs from 'dayjs'
 import 'dayjs/locale/zh-cn'
 dayjs.locale('zh-cn')
-const toDayDate = dayjs().format('YYYY年MM月DD日 dddd')
 
 //初始组合式
 const router = useRouter()
@@ -54,6 +53,7 @@ const store = useAppStore()
 
 //项目信息
 const projectInfo = ref(store.projectInfo)
+const toDayDate = dayjs().format('YYYY年MM月DD日 dddd')
 
 onMounted(() => {
     projectInfo.value = store.projectInfo
@@ -208,5 +208,5 @@ const openDevTools = () => {
 </script>
 
 <style lang="scss">
-@import '~src/styles/home';
+@import '../styles/home';
 </style>

+ 9 - 3
src/renderer/src/views/query.vue

@@ -52,6 +52,9 @@
                     </div>
                 </el-popover>
             </template>
+            <template #extra>
+                <el-button hc-btn @click="toHomePage">返回主页</el-button>
+            </template>
             <hc-table :column="tableColumn" :datas="tableData" :loading="tableLoading" :is-index="false" is-new>
                 <template #title="{ row }">
                     <el-link type="primary" :underline="false" @click="tableRowTitle(row)">{{ row?.title }}</el-link>
@@ -71,13 +74,11 @@
 <script setup>
 import { nextTick, onMounted, ref } from 'vue'
 import { useAppStore } from '~src/store'
-import { useRouter } from 'vue-router'
 import { sql_count, sql_table } from '../utils/dbConnect'
 import { getArrValue, isNullES } from 'js-fast-way'
 import QueryFileRoll from '../components/query/file-roll.vue'
 
 //初始组合式
-const router = useRouter()
 const store = useAppStore()
 
 //项目信息
@@ -232,8 +233,13 @@ const fileRollDrawerClose = () => {
     isFileRollDrawer.value = false
     fileRollRow.value = {}
 }
+
+//返回主页
+const toHomePage = async () => {
+    window.open('/home', '_self')
+}
 </script>
 
 <style lang="scss">
-@import '~src/styles/query';
+@import '../styles/query';
 </style>