package.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/assets/styles/element-ui.scss | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/components/filePreview/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/main.js | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/salesManagement/salesLedger/fileList.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
package.json
@@ -17,6 +17,8 @@ }, "dependencies": { "@element-plus/icons-vue": "2.3.1", "@vue-office/docx": "^1.6.3", "@vue-office/excel": "^1.7.14", "@vueup/vue-quill": "1.2.0", "@vueuse/core": "10.11.0", "axios": "0.28.1", src/assets/styles/element-ui.scss
@@ -56,18 +56,18 @@ padding: 0 !important; } .el-dialog__header { background: #F5F6F7; background: #f5f6f7; padding: 12px 16px; border-radius: 8px 8px 0 0; } .el-dialog__title { font-weight: 400; font-size: 16px; color: #2E3033; color: #2e3033; } .el-dialog__body { padding: 16px 40px 0 40px; max-height: 680px; max-height: 90vh; overflow-y: auto; } .el-dialog__footer { @@ -79,14 +79,14 @@ border-radius: 8px; } .el-message-box__header { background: #F5F6F7; background: #f5f6f7; padding: 12px 16px; border-radius: 8px 8px 0 0; } .el-message-box__title { font-weight: 400; font-size: 16px; color: #2E3033; color: #2e3033; } .el-message-box__content { padding: 16px 40px 0 40px; @@ -108,7 +108,7 @@ .el-table__expanded-cell { padding: 0 !important; .el-table__header-wrapper { background-color: #F5F8FF !important; background-color: #f5f8ff !important; } } @@ -127,7 +127,7 @@ // dropdown .el-dropdown-menu { a { display: block display: block; } } @@ -149,6 +149,6 @@ display: none; } .el-dropdown .el-dropdown-link{ .el-dropdown .el-dropdown-link { color: var(--el-color-primary) !important; } } src/components/filePreview/index.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,201 @@ <template> <el-dialog v-model="dialogVisible" title="é¢è§" width="100%" fullscreen align-center :before-close="handleClose" append-to-body> <div> <!-- å¾çé¢è§ --> <div v-if="isImage"> <img :src="imgUrl" alt="Image Preview" /> </div> <!-- PDFé¢è§æç¤º --> <div v-if="isPdf" style="height: 100vh; display: flex; align-items: center; justify-content: center;"> <p>æ£å¨åå¤PDFé¢è§...</p> </div> <!-- Wordææ¡£é¢è§ --> <div v-if="isDoc"> <p v-if="!isDocShow">ææ¡£æ æ³ç´æ¥é¢è§ï¼è¯·ä¸è½½æ¥çã</p> <a :href="fileUrl" v-if="!isDocShow">ä¸è½½æä»¶</a> <vue-office-docx v-else :src="fileUrl" style="height: 100vh;" @rendered="renderedHandler" @error="errorHandler" /> </div> <!-- Excelææ¡£é¢è§ --> <div v-if="isXls"> <p v-if="!isDocShow">ææ¡£æ æ³ç´æ¥é¢è§ï¼è¯·ä¸è½½æ¥çã</p> <a :href="fileUrl" v-if="!isDocShow">ä¸è½½æä»¶</a> <vue-office-excel v-else :src="fileUrl" :options="options" style="height: 100vh;" @rendered="renderedHandler" @error="errorHandler" /> </div> <!-- å缩æä»¶å¤ç --> <div v-if="isZipOrRar"> <p>å缩æä»¶æ æ³ç´æ¥é¢è§ï¼è¯·ä¸è½½æ¥çã</p> <a :href="fileUrl">ä¸è½½æä»¶</a> </div> <!-- 䏿¯æçæ ¼å¼ --> <div v-if="!isSupported"> <p>䏿¯æçæä»¶æ ¼å¼</p> </div> </div> </el-dialog> </template> <script setup> import { ref, computed, getCurrentInstance, watch } from 'vue'; import VueOfficeDocx from '@vue-office/docx'; import '@vue-office/docx/lib/index.css'; import VueOfficeExcel from '@vue-office/excel'; import '@vue-office/excel/lib/index.css'; // ååºå¼åé const fileUrl = ref('') const dialogVisible = ref(false) const { proxy } = getCurrentInstance(); const javaApi = proxy.javaApi; // ææ¡£é¢è§ç¶æ const isDocShow = ref(true); const imgUrl = ref(''); const options = ref({ xls: false, minColLength: 0, minRowLength: 0, widthOffset: 10, heightOffset: 10, beforeTransformData: (workbookData) => workbookData, transformData: (workbookData) => workbookData, }); // 计ç®å±æ§ - 夿æä»¶ç±»å const isImage = computed(() => { const state = /\.(jpg|jpeg|png|gif)$/i.test(fileUrl.value); if (state) { imgUrl.value = fileUrl.value.replaceAll('word', 'img'); } return state; }); const isPdf = computed(() => { return /\.pdf$/i.test(fileUrl.value); }); const isDoc = computed(() => { return /\.(doc|docx)$/i.test(fileUrl.value); }); const isXls = computed(() => { const state = /\.(xls|xlsx)$/i.test(fileUrl.value); if (state) { options.value.xls = /\.(xls)$/i.test(fileUrl.value); } return state; }); const isZipOrRar = computed(() => { return /\.(zip|rar)$/i.test(fileUrl.value); }); const isSupported = computed(() => { return isImage.value || isPdf.value || isDoc.value || isXls.value || isZipOrRar.value; }); // 卿å建aæ ç¾å¹¶è·³è½¬é¢è§PDF const previewPdf = (url) => { // å建aæ ç¾ const link = document.createElement('a'); // 设置PDFæä»¶URL link.href = url; // 卿°æ ç¾é¡µæå¼ link.target = '_blank'; // å®å ¨å±æ§ï¼é²æ¢æ°é¡µé¢è®¿é®åé¡µé¢ link.rel = 'noopener noreferrer'; // å¯éï¼è®¾ç½®é¾æ¥ææ¬ link.textContent = 'é¢è§PDF'; // å°aæ ç¾æ·»å å°é¡µé¢ï¼é¨åæµè§å¨è¦æ±å¿ é¡»å¨DOMä¸ï¼ document.body.appendChild(link); // 触åç¹å»äºä»¶ link.click(); // ç§»é¤aæ ç¾ï¼æ¸ çDOM document.body.removeChild(link); }; // çå¬PDFç¶æååï¼èªå¨è§¦å跳转 watch( () => isPdf.value, (newVal) => { // å½ç¡®è®¤æ¯PDF䏿件URLæææ¶ if (newVal && fileUrl.value) { // å ³éå¯¹è¯æ¡ dialogVisible.value = false; // å 个å°å»¶è¿ç¡®ä¿ç¶ææ´æ°å®æ setTimeout(() => { previewPdf(fileUrl.value); fileUrl.value = ''; }, 100); } } ); // æ¹æ³å®ä¹ const renderedHandler = () => { console.log("渲æå®æ"); isDocShow.value = true; resetStyle(); }; const errorHandler = () => { console.log("渲æå¤±è´¥"); isDocShow.value = false; }; const open = (url) => { fileUrl.value = javaApi + url; dialogVisible.value = true; }; const handleClose = () => { dialogVisible.value = false; }; const resetStyle = () => { const elements = document.querySelectorAll('[style*="pt"]'); for (const element of elements) { const style = element.getAttribute('style'); if (style) { element.setAttribute('style', style.replace(/pt/g, 'px')); } } }; // æ´é²openæ¹æ³ä¾å¤é¨è°ç¨ defineExpose({ open }) </script> <style scoped> img { max-width: 100%; display: block; margin: 0 auto; } .oneLine { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } </style> src/main.js
@@ -1,68 +1,81 @@ import { createApp } from 'vue' import { createApp } from "vue"; import Cookies from 'js-cookie' import Cookies from "js-cookie"; import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import 'element-plus/theme-chalk/dark/css-vars.css' import locale from 'element-plus/es/locale/lang/zh-cn' import ElementPlus from "element-plus"; import "element-plus/dist/index.css"; import "element-plus/theme-chalk/dark/css-vars.css"; import locale from "element-plus/es/locale/lang/zh-cn"; import '@/assets/styles/index.scss' // global css import "@/assets/styles/index.scss"; // global css import App from './App' import store from './store' import router from './router' import directive from './directive' // directive import App from "./App"; import store from "./store"; import router from "./router"; import directive from "./directive"; // directive // 注åæä»¤ import plugins from './plugins' // plugins import { download } from '@/utils/request' import plugins from "./plugins"; // plugins import { download } from "@/utils/request"; // svg徿 import 'virtual:svg-icons-register' import SvgIcon from '@/components/SvgIcon' import elementIcons from '@/components/SvgIcon/svgicon' import "virtual:svg-icons-register"; import SvgIcon from "@/components/SvgIcon"; import elementIcons from "@/components/SvgIcon/svgicon"; import './permission' // permission control import "./permission"; // permission control import { useDict } from '@/utils/dict' import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels } from '@/utils/ruoyi' import { useDict } from "@/utils/dict"; import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels, } from "@/utils/ruoyi"; // å页ç»ä»¶ import Pagination from '@/components/Pagination' import Pagination from "@/components/Pagination"; // èªå®ä¹è¡¨æ ¼å·¥å ·ç»ä»¶ import RightToolbar from '@/components/RightToolbar' import RightToolbar from "@/components/RightToolbar"; // 坿æ¬ç»ä»¶ import Editor from "@/components/Editor" import Editor from "@/components/Editor"; // æä»¶ä¸ä¼ ç»ä»¶ import FileUpload from "@/components/FileUpload" import FileUpload from "@/components/FileUpload"; // å¾çä¸ä¼ ç»ä»¶ import ImageUpload from "@/components/ImageUpload" import ImageUpload from "@/components/ImageUpload"; // å¾çé¢è§ç»ä»¶ import ImagePreview from "@/components/ImagePreview" import ImagePreview from "@/components/ImagePreview"; // åå ¸æ ç¾ç»ä»¶ import DictTag from '@/components/DictTag' import DictTag from "@/components/DictTag"; // è¡¨æ ¼ç»ä»¶ import PIMTable from "@/components/PIMTable/PIMTable.vue"; import { getToken } from "@/utils/auth"; import {calculateTaxExclusiveTotalPrice, summarizeTable,calculateTaxIncludeTotalPrice} from "@/utils/summarizeTable.js"; import { calculateTaxExclusiveTotalPrice, summarizeTable, calculateTaxIncludeTotalPrice, } from "@/utils/summarizeTable.js"; const app = createApp(App) const app = createApp(App); // å ¨å±æ¹æ³æè½½ app.config.globalProperties.useDict = useDict app.config.globalProperties.download = download app.config.globalProperties.parseTime = parseTime app.config.globalProperties.resetForm = resetForm app.config.globalProperties.summarizeTable = summarizeTable app.config.globalProperties.calculateTaxExclusiveTotalPrice = calculateTaxExclusiveTotalPrice app.config.globalProperties.calculateTaxIncludeTotalPrice = calculateTaxIncludeTotalPrice app.config.globalProperties.handleTree = handleTree app.config.globalProperties.addDateRange = addDateRange app.config.globalProperties.selectDictLabel = selectDictLabel app.config.globalProperties.selectDictLabels = selectDictLabels app.config.globalProperties.javaApi = 'http://114.132.189.42:8078' app.config.globalProperties.useDict = useDict; app.config.globalProperties.download = download; app.config.globalProperties.parseTime = parseTime; app.config.globalProperties.resetForm = resetForm; app.config.globalProperties.summarizeTable = summarizeTable; app.config.globalProperties.calculateTaxExclusiveTotalPrice = calculateTaxExclusiveTotalPrice; app.config.globalProperties.calculateTaxIncludeTotalPrice = calculateTaxIncludeTotalPrice; app.config.globalProperties.handleTree = handleTree; app.config.globalProperties.addDateRange = addDateRange; app.config.globalProperties.selectDictLabel = selectDictLabel; app.config.globalProperties.selectDictLabels = selectDictLabels; app.config.globalProperties.javaApi = "http://114.132.189.42:8099"; app.config.globalProperties.HaveJson = (val) => { return JSON.parse(JSON.stringify(val)); }; @@ -71,29 +84,29 @@ }; // å ¨å±ç»ä»¶æè½½ app.component('DictTag', DictTag) app.component('Pagination', Pagination) app.component('FileUpload', FileUpload) app.component('ImageUpload', ImageUpload) app.component('ImagePreview', ImagePreview) app.component('RightToolbar', RightToolbar) app.component('Editor', Editor) app.component('PIMTable', PIMTable) app.component("DictTag", DictTag); app.component("Pagination", Pagination); app.component("FileUpload", FileUpload); app.component("ImageUpload", ImageUpload); app.component("ImagePreview", ImagePreview); app.component("RightToolbar", RightToolbar); app.component("Editor", Editor); app.component("PIMTable", PIMTable); app.use(router) app.use(store) app.use(plugins) app.use(elementIcons) app.component('svg-icon', SvgIcon) app.use(router); app.use(store); app.use(plugins); app.use(elementIcons); app.component("svg-icon", SvgIcon); directive(app) directive(app); // 使ç¨element-plus å¹¶ä¸è®¾ç½®å ¨å±çå¤§å° app.use(ElementPlus, { locale: locale, // æ¯æ largeãdefaultãsmall size: Cookies.get('size') || 'default' }) app._context.components.ElDialog.props.closeOnClickModal.default = false size: Cookies.get("size") || "default", }); app._context.components.ElDialog.props.closeOnClickModal.default = false; app.mount('#app') app.mount("#app"); src/views/salesManagement/salesLedger/fileList.vue
@@ -1,22 +1,26 @@ <template> <el-dialog v-model="dialogVisible" title="éä»¶" width="30%" :before-close="handleClose"> <el-dialog v-model="dialogVisible" title="éä»¶" width="40%" :before-close="handleClose"> <el-table :data="tableData" border height="40vh"> <el-table-column label="éä»¶åç§°" prop="name" min-width="400" show-overflow-tooltip /> <el-table-column fixed="right" label="æä½" width="100" align="center"> <template #default="scope"> <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">ä¸è½½</el-button> <el-button link type="primary" size="small" @click="lookFile(scope.row)">é¢è§</el-button> </template> </el-table-column> </el-table> </el-dialog> <filePreview ref="filePreviewRef" /> </template> <script setup> import { ref } from 'vue' import filePreview from '@/components/filePreview/index.vue' const dialogVisible = ref(false) const tableData = ref([]) const { proxy } = getCurrentInstance(); const filePreviewRef = ref() const handleClose = () => { dialogVisible.value = false } @@ -28,6 +32,9 @@ proxy.$download.name(row.url); } const lookFile = (row) => { filePreviewRef.value.open(row.url) } defineExpose({ open })