| | |
| | | *.njsproj |
| | | *.sln |
| | | *.sw? |
| | | |
| | | #Electron-builder output |
| | | /dist_electron |
| | |
| | | "scripts": { |
| | | "serve": "vue-cli-service serve", |
| | | "build": "vue-cli-service build", |
| | | "lint": "vue-cli-service lint" |
| | | "lint": "vue-cli-service lint", |
| | | "electron:build": "vue-cli-service electron:build", |
| | | "electron:serve": "vue-cli-service electron:serve", |
| | | "postinstall": "electron-builder install-app-deps", |
| | | "postuninstall": "electron-builder install-app-deps" |
| | | }, |
| | | "main": "background.js", |
| | | "dependencies": { |
| | | "core-js": "^3.6.5", |
| | | "vue": "^2.6.11" |
| | | "vue": "^2.6.11", |
| | | "vue-router": "3.0.6", |
| | | "axios": "0.18.1", |
| | | "element-ui": "^2.15.6", |
| | | "echarts": "^4.8.0", |
| | | "echarts-liquidfill": "^2.0.6" |
| | | }, |
| | | "devDependencies": { |
| | | "@vue/cli-plugin-babel": "~4.5.13", |
| | | "@vue/cli-plugin-eslint": "~4.5.13", |
| | | "@vue/cli-service": "~4.5.13", |
| | | "babel-eslint": "^10.1.0", |
| | | "electron": "^13.0.0", |
| | | "electron-devtools-installer": "^3.1.0", |
| | | "eslint": "^6.7.2", |
| | | "less": "^3.12.2", |
| | | "less-loader": "^6.2.0", |
| | | "eslint-plugin-vue": "^6.2.2", |
| | | "vue-cli-plugin-electron-builder": "~2.1.1", |
| | | "vue-template-compiler": "^2.6.11" |
| | | }, |
| | | "eslintConfig": { |
| | |
| | | "parserOptions": { |
| | | "parser": "babel-eslint" |
| | | }, |
| | | "rules": {} |
| | | "rules": { |
| | | "no-unused-vars": "off", |
| | | "vue/no-unused-components": "off", |
| | | "no-debugger": "off" |
| | | } |
| | | }, |
| | | "browserslist": [ |
| | | "> 1%", |
| | |
| | | <template> |
| | | <div id="app"> |
| | | <img alt="Vue logo" src="./assets/logo.png"> |
| | | <HelloWorld msg="Welcome to Your Vue.js App"/> |
| | | <div class="main"> |
| | | <div class="left" ref="left"> |
| | | <menu-list></menu-list> |
| | | <div class="title">文件列表</div> |
| | | <div class="file-list" @contextmenu.prevent="openContextMenu($event)"> |
| | | <el-tree |
| | | :data="stationData" |
| | | @node-click="handleNodeClick" |
| | | @node-contextmenu="nodeContextClick" |
| | | ></el-tree> |
| | | </div> |
| | | </div> |
| | | <div class="handle" ref="handle"></div> |
| | | <div class="right"> |
| | | <div class="" @click="select">选文件</div> |
| | | <div class="">当前选中的文件夹为:{{ path }}</div> |
| | | <router-view /> |
| | | </div> |
| | | </div> |
| | | <!-- 右键菜单 --> |
| | | <context-menu |
| | | v-model="contextMenu.visible" |
| | | :disabled-list="disabledList" |
| | | :style="{ left: contextMenu.x + 'px', top: contextMenu.y + 'px' }" |
| | | ></context-menu> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import HelloWorld from './components/HelloWorld.vue' |
| | | const minWidth = 200, |
| | | maxWidth = 600; |
| | | |
| | | import MenuList from "@/components/menuList"; |
| | | import ContextMenu from "@/components/contextMenu"; |
| | | import { getStation } from "./apis"; |
| | | |
| | | export default { |
| | | name: 'App', |
| | | name: "App", |
| | | components: { |
| | | HelloWorld |
| | | MenuList, |
| | | ContextMenu, |
| | | }, |
| | | data() { |
| | | return { |
| | | path: "", |
| | | startX: 0, |
| | | leftW: 0, |
| | | stationData: [], |
| | | contextMenu: { |
| | | x: 0, |
| | | y: 0, |
| | | visible: false, |
| | | }, |
| | | disabledList: [], |
| | | }; |
| | | }, |
| | | methods: { |
| | | select() { |
| | | window.api.send("open-file-dialog"); |
| | | }, |
| | | onMouseDown(e) { |
| | | // const el = e.target; |
| | | this.startX = e.clientX; |
| | | this.leftW = this.$refs.left.clientWidth; |
| | | document.addEventListener("mousemove", this.onMouseMove); |
| | | document.addEventListener("mouseup", this.onMouseUp); |
| | | }, |
| | | onMouseUp() { |
| | | // this.$refs.handle.style.background = 'transparent'; |
| | | // document.removeEventListener('mousedown', this.onMouseDown); |
| | | document.removeEventListener("mousemove", this.onMouseMove); |
| | | }, |
| | | onMouseMove(e) { |
| | | const el = this.$refs.handle; |
| | | const left = this.$refs.left; |
| | | const endX = e.clientX; |
| | | const moveLen = endX - this.startX; |
| | | const CurBoxLen = this.leftW + moveLen; |
| | | if (CurBoxLen <= minWidth || CurBoxLen >= maxWidth) { |
| | | return; |
| | | } |
| | | left.style.width = CurBoxLen + "px"; |
| | | el.style.left = CurBoxLen + "px"; |
| | | }, |
| | | getStation() { |
| | | getStation().then((res) => { |
| | | const { code, data, data2 } = res.data; |
| | | let list = []; |
| | | if (code && data) { |
| | | console.log(1, data2); |
| | | list = this.formatData(data2); |
| | | } |
| | | this.stationData = list; |
| | | }); |
| | | }, |
| | | formatData(data) { |
| | | let res = data.map((v) => { |
| | | let sname2s = []; |
| | | v.sname2s.forEach((val) => { |
| | | if (val.station2 != "-") { |
| | | let children = []; |
| | | val.sname3s.forEach((item) => { |
| | | if (item.station3 != "-") { |
| | | children.push({ |
| | | label: item.station3, |
| | | children: item.fileNames.map((item1) => ({ |
| | | label: item1.fileName, |
| | | url: item1.fileUrl, |
| | | level: 3, |
| | | })), |
| | | level: 2, |
| | | }); |
| | | } else { |
| | | children.push( |
| | | ...item.fileNames.map((item1) => ({ |
| | | label: item1.fileName, |
| | | url: item1.fileUrl, |
| | | level: 3, |
| | | })) |
| | | ); |
| | | } |
| | | }); |
| | | sname2s.push({ |
| | | label: val.station2, |
| | | children, |
| | | level: 1, |
| | | }); |
| | | } else { |
| | | sname2s.push( |
| | | ...val.sname3s[0].fileNames.map((item) => ({ |
| | | label: item.fileName, |
| | | url: item.fileUrl, |
| | | level: 3, |
| | | })) |
| | | ); |
| | | } |
| | | }); |
| | | return { |
| | | children: sname2s, |
| | | label: v.station1, |
| | | level: 0, |
| | | }; |
| | | }); |
| | | console.log(res); |
| | | return res; |
| | | }, |
| | | handleNodeClick(obj) { |
| | | console.log(123, obj); |
| | | }, |
| | | nodeContextClick($e, obj) { |
| | | console.log(obj); |
| | | const { clientX, clientY } = $e; |
| | | this.contextMenu.x = clientX; |
| | | let y = clientY; |
| | | let bodyHeight = document.body.clientHeight; |
| | | if (y + 180 > bodyHeight) { |
| | | y = bodyHeight - 180; |
| | | } |
| | | this.contextMenu.y = y; |
| | | switch (obj.level) { |
| | | case 0: |
| | | case 1: |
| | | case 2: |
| | | // 子站上按鼠标右键,不能“打开文件”、“新建根文件” |
| | | this.disabledList = [0, 11]; |
| | | break; |
| | | case 3: |
| | | // 添加的测试文件上按鼠标右键,可以点击“打开文件”、“重命名”、“删除” |
| | | this.disabledList = [1, 2]; |
| | | break; |
| | | default: |
| | | return false; |
| | | } |
| | | this.contextMenu.visible = true; |
| | | }, |
| | | // 右键菜单 |
| | | openContextMenu($e) { |
| | | // console.log($e, "context"); |
| | | const { |
| | | clientX, |
| | | clientY, |
| | | target: { classList }, |
| | | } = $e; |
| | | this.contextMenu.x = clientX; |
| | | let y = clientY; |
| | | let bodyHeight = document.body.clientHeight; |
| | | if (y + 180 > bodyHeight) { |
| | | y = bodyHeight - 180; |
| | | } |
| | | this.contextMenu.y = y; |
| | | if (classList.contains("file-list")) { |
| | | // 在空白处点击的右键 只能新建 |
| | | this.disabledList = [0, 12, 2, 3, 4]; |
| | | |
| | | this.contextMenu.visible = true; |
| | | } |
| | | }, |
| | | closeContextMenu() { |
| | | this.contextMenu.visible = false; |
| | | }, |
| | | maskClick() { |
| | | this.closeContextMenu(); |
| | | }, |
| | | }, |
| | | mounted() { |
| | | window.api.receive("selected-directory", (path) => { |
| | | this.path = path.filePaths; |
| | | }); |
| | | let handle = this.$refs.handle; |
| | | handle.addEventListener("mousedown", this.onMouseDown); |
| | | this.getStation(); |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style> |
| | | html, |
| | | body { |
| | | height: 100%; |
| | | margin: 0; |
| | | padding: 0; |
| | | overflow: hidden; |
| | | } |
| | | #app { |
| | | height: 100%; |
| | | font-family: Avenir, Helvetica, Arial, sans-serif; |
| | | -webkit-font-smoothing: antialiased; |
| | | -moz-osx-font-smoothing: grayscale; |
| | | text-align: center; |
| | | color: #2c3e50; |
| | | margin-top: 60px; |
| | | color: #000; |
| | | background: #fff; |
| | | } |
| | | ul, |
| | | li { |
| | | list-style: none; |
| | | margin: 0; |
| | | padding: 0; |
| | | user-select: none; |
| | | } |
| | | </style> |
| | | <style lang="less" scoped> |
| | | .main { |
| | | height: 100%; |
| | | position: relative; |
| | | display: flex; |
| | | } |
| | | .left { |
| | | width: 14em; |
| | | box-shadow: 1px 0 2px -1px #000; |
| | | /* background: rgba(200, 200, 200, .8); */ |
| | | display: flex; |
| | | flex-direction: column; |
| | | .title { |
| | | background: #999; |
| | | padding: 4px; |
| | | } |
| | | .file-list { |
| | | flex: 1; |
| | | overflow-y: auto; |
| | | text-align: left; |
| | | /deep/ .el-tree { |
| | | color: #333; |
| | | display: inline-block; |
| | | .el-tree-node__content { |
| | | display: inline-block; |
| | | } |
| | | // .el-tree-node.is-expanded>.el-tree-node__children { |
| | | // display: inline-block; |
| | | // } |
| | | } |
| | | } |
| | | } |
| | | .handle { |
| | | width: 6px; |
| | | position: absolute; |
| | | top: 0; |
| | | bottom: 0; |
| | | left: 14em; |
| | | background: transparent; |
| | | cursor: col-resize; |
| | | } |
| | | .handle:hover { |
| | | background: rgba(200, 200, 200, 0.6); |
| | | } |
| | | .right { |
| | | /* background: rgba(0,0,0,.4); */ |
| | | flex: 1; |
| | | } |
| | | .context-menu { |
| | | position: absolute; |
| | | z-index: 100; |
| | | background: #fff; |
| | | border: 1px #ccc solid; |
| | | border-radius: 4px; |
| | | padding: 4px; |
| | | .main-ul { |
| | | display: flex; |
| | | flex-direction: column; |
| | | .main-li { |
| | | cursor: pointer; |
| | | flex: 1; |
| | | border: 1px #ccc solid; |
| | | padding: 4px; |
| | | &:hover { |
| | | background: #f0f0f0; |
| | | } |
| | | & ~ .main-li { |
| | | margin-top: 2px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .trans-mask { |
| | | position: fixed; |
| | | z-index: 99; |
| | | left: 0; |
| | | top: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background: transparent; |
| | | } |
| | | </style> |
New file |
| | |
| | | import axios from "@/assets/js/axios"; |
| | | |
| | | /** |
| | | * 查询台站列表 |
| | | */ |
| | | export const getStation = () => { |
| | | return axios({ |
| | | method: "GET", |
| | | url: "station/getStation" |
| | | }) |
| | | } |
| | | |
| | | /** |
| | | * 台站下添加文件 |
| | | */ |
| | | export const addFileInStation = (params) => { |
| | | return axios({ |
| | | method: "GET", |
| | | url: "stationInfo/addFileInStation", |
| | | params |
| | | }) |
| | | } |
| | | /** |
| | | * 添加台站 |
| | | */ |
| | | export const addStation = (params) => { |
| | | return axios({ |
| | | method: "GET", |
| | | url: "stationInfo/addStation", |
| | | params |
| | | }) |
| | | } |
| | | /** |
| | | * 删除台站 |
| | | */ |
| | | export const deleteStation = (params) => { |
| | | return axios({ |
| | | method: "GET", |
| | | url: "stationInfo/deleteStation", |
| | | params |
| | | }) |
| | | } |
| | | /** |
| | | * 编辑台站 |
| | | */ |
| | | export const updateStation = (params) => { |
| | | return axios({ |
| | | method: "GET", |
| | | url: "stationInfo/updateStation", |
| | | params |
| | | }) |
| | | } |
| | | /** |
| | | * 解析xml文件 |
| | | */ |
| | | export const getXmlValue = (params) => { |
| | | return axios({ |
| | | method: "GET", |
| | | url: "fileInfo/getXmlValue", |
| | | params |
| | | }) |
| | | } |
New file |
| | |
| | | import axios from 'axios'; |
| | | |
| | | axios.defaults.baseURL = 'http://localhost:8093/res/'; |
| | | axios.defaults.withCredentials = true; // 保持请求头 |
| | | |
| | | |
| | | // 添加响应拦截器 |
| | | axios.interceptors.response.use(function (response) { |
| | | // 对响应数据做点什么 |
| | | return response; |
| | | }, function (error) { |
| | | return Promise.reject(error); |
| | | }); |
| | | |
| | | export default axios; |
New file |
| | |
| | | 'use strict' |
| | | |
| | | import { app, protocol, BrowserWindow, ipcMain, ipcRenderer, dialog } from 'electron' |
| | | import { createProtocol } from 'vue-cli-plugin-electron-builder/lib' |
| | | import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer' |
| | | import path from 'path'; |
| | | import child_process from 'child_process'; |
| | | |
| | | const isDevelopment = process.env.NODE_ENV !== 'production' |
| | | // const path = require('path'); |
| | | |
| | | // Scheme must be registered before the app is ready |
| | | protocol.registerSchemesAsPrivileged([ |
| | | { scheme: 'app', privileges: { secure: true, standard: true } } |
| | | ]) |
| | | |
| | | async function createWindow() { |
| | | // Create the browser window. |
| | | const win = new BrowserWindow({ |
| | | width: 800, |
| | | height: 600, |
| | | webPreferences: { |
| | | // Use pluginOptions.nodeIntegration, leave this alone |
| | | // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info |
| | | // nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION, |
| | | // contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION |
| | | nodeIntegration: false, |
| | | webSecurity: true, |
| | | allowEval: false, |
| | | allowRunningInsecureContent: false, |
| | | contextIsolation: true, |
| | | enableRemoteModule: false, |
| | | preload: path.join(__dirname, 'preload.js') |
| | | } |
| | | }) |
| | | |
| | | if (process.env.WEBPACK_DEV_SERVER_URL) { |
| | | // Load the url of the dev server if in development mode |
| | | await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL) |
| | | if (!process.env.IS_TEST) win.webContents.openDevTools() |
| | | } else { |
| | | createProtocol('app') |
| | | // Load the index.html when not in development |
| | | win.loadURL('app://./index.html') |
| | | } |
| | | } |
| | | |
| | | // Quit when all windows are closed. |
| | | app.on('window-all-closed', () => { |
| | | // On macOS it is common for applications and their menu bar |
| | | // to stay active until the user quits explicitly with Cmd + Q |
| | | if (process.platform !== 'darwin') { |
| | | app.quit() |
| | | } |
| | | }) |
| | | |
| | | app.on('activate', () => { |
| | | // On macOS it's common to re-create a window in the app when the |
| | | // dock icon is clicked and there are no other windows open. |
| | | if (BrowserWindow.getAllWindows().length === 0) createWindow() |
| | | }) |
| | | |
| | | // This method will be called when Electron has finished |
| | | // initialization and is ready to create browser windows. |
| | | // Some APIs can only be used after this event occurs. |
| | | app.on('ready', async () => { |
| | | // if (isDevelopment && !process.env.IS_TEST) { |
| | | // // Install Vue Devtools |
| | | // try { |
| | | // await installExtension(VUEJS_DEVTOOLS) |
| | | // } catch (e) { |
| | | // console.error('Vue Devtools failed to install:', e.toString()) |
| | | // } |
| | | // } |
| | | createWindow() |
| | | }) |
| | | |
| | | // ipcMain 事件处理 |
| | | // ipcMain.on('open-file-dialog', (event) => { |
| | | // dialog.showOpenDialog({ |
| | | // properties: ['openFile', 'openDirectory'] |
| | | // }, (files) => { |
| | | // // child_process.spawn('cmd.exe', ['/c', 'echo '+JSON.stringify(files)+' success >> 112233.txt']) |
| | | // if(files) { |
| | | // event.sender.send('selected-directory', files); |
| | | // } |
| | | // }) |
| | | // }); |
| | | ipcMain.on('open-file-dialog', (event) => { |
| | | dialog.showOpenDialog({ |
| | | filters: [{ name: 'xml', extensions: ['xml'] }], |
| | | properties: ['openFile'] |
| | | }).then((files) => { |
| | | if (files) { |
| | | event.sender.send('selected-file', files); |
| | | } |
| | | }) |
| | | }); |
| | | ipcMain.on('open-directory-dialog', (event) => { |
| | | dialog.showOpenDialog({ |
| | | properties: ['openDirectory'] |
| | | }).then((files) => { |
| | | if (files) { |
| | | event.sender.send('selected-directory', files); |
| | | } |
| | | }) |
| | | }); |
| | | |
| | | // Exit cleanly on request from parent process in development mode. |
| | | if (isDevelopment) { |
| | | if (process.platform === 'win32') { |
| | | process.on('message', (data) => { |
| | | if (data === 'graceful-exit') { |
| | | app.quit() |
| | | } |
| | | }) |
| | | } else { |
| | | process.on('SIGTERM', () => { |
| | | app.quit() |
| | | }) |
| | | } |
| | | } |
New file |
| | |
| | | <template> |
| | | <div class="context-menu" v-show="visible"> |
| | | <!-- mask --> |
| | | <div |
| | | class="mask" |
| | | v-show="visible" |
| | | @click="close" |
| | | @contextmenu="close" |
| | | ></div> |
| | | <div class="contain"> |
| | | <ul class="main-ul"> |
| | | <li |
| | | class="main-li" |
| | | v-for="(item, idx) in menuList" |
| | | :key="'main_' + idx" |
| | | > |
| | | <div |
| | | :class="['title', {disabled: item.disabled}]" |
| | | @click="itemClick(item)" |
| | | @mouseenter="itemHover(item)" |
| | | > |
| | | {{ item.title }} |
| | | </div> |
| | | <ul |
| | | class="sub-ul" |
| | | v-show="item.visible && item.children && item.children.length" |
| | | > |
| | | <li |
| | | :class="['sub-li', {disabled: subItem.disabled}]" |
| | | v-for="(subItem, index) in item.children" |
| | | :key="'sub_' + index" |
| | | @click="itemClick(subItem)" |
| | | > |
| | | {{ subItem.title }} |
| | | </li> |
| | | </ul> |
| | | </li> |
| | | </ul> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "ContextMenu", |
| | | model: { |
| | | prop: "visible", |
| | | event: "change", |
| | | }, |
| | | props: { |
| | | visible: { |
| | | type: Boolean, |
| | | required: true, |
| | | default: false, |
| | | }, |
| | | disabledList: { |
| | | type: Array, |
| | | default() { |
| | | return []; |
| | | }, |
| | | }, |
| | | }, |
| | | data() { |
| | | const menuList = [ |
| | | { |
| | | id: 0, |
| | | title: "打开文件", |
| | | method: "openFile", |
| | | disabled: false, |
| | | visible: false, |
| | | }, |
| | | { |
| | | id: 1, |
| | | title: "新建", |
| | | disabled: false, |
| | | visible: false, |
| | | children: [ |
| | | { |
| | | id: 11, |
| | | title: "新建根文件", |
| | | // method: "openFile", |
| | | disabled: false, |
| | | }, |
| | | { |
| | | id: 12, |
| | | title: "新建子文件", |
| | | // method: "openFile", |
| | | disabled: false, |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | id: 2, |
| | | title: "添加", |
| | | disabled: false, |
| | | visible: false, |
| | | children: [ |
| | | { |
| | | id: 13, |
| | | title: "指定目录下所有文件", |
| | | disabled: false, |
| | | }, |
| | | { |
| | | id: 14, |
| | | title: "单一文件", |
| | | disabled: false, |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | id: 3, |
| | | title: "重命名", |
| | | method: "openFile", |
| | | disabled: false, |
| | | visible: false, |
| | | }, |
| | | { |
| | | id: 4, |
| | | title: "删除", |
| | | method: "openFile", |
| | | disabled: false, |
| | | visible: false, |
| | | }, |
| | | ]; |
| | | return { |
| | | menuList, |
| | | }; |
| | | }, |
| | | components: {}, |
| | | watch: { |
| | | visible(n) { |
| | | if(n) { |
| | | this.initData(); |
| | | } |
| | | } |
| | | }, |
| | | methods: { |
| | | itemClick(obj) { |
| | | // console.log(obj) |
| | | if (obj.method && "function" == typeof this[obj.method] && !obj.disabled) { |
| | | this.close(); |
| | | this[obj.method](obj); |
| | | } |
| | | }, |
| | | close() { |
| | | this.invisibleSubMenu(); |
| | | this.$emit("change", false); |
| | | }, |
| | | showChildren(obj) { |
| | | // this.menuList.forEach((v) => { |
| | | // v.visible = false; |
| | | // }); |
| | | obj.visible = true; |
| | | }, |
| | | invisibleSubMenu() { |
| | | this.menuList.forEach((v) => { |
| | | v.visible = false; |
| | | }); |
| | | }, |
| | | itemHover(obj) { |
| | | if (obj.disabled) { |
| | | return false; |
| | | } |
| | | this.invisibleSubMenu(); |
| | | this.$nextTick(() => { |
| | | obj.visible = true; |
| | | }); |
| | | }, |
| | | openFile() { |
| | | // console.log("openfile"); |
| | | window.api.send("open-file-dialog"); |
| | | }, |
| | | initEvents() { |
| | | window.api.receive("selected-file", (path) => { |
| | | console.log(path.filePaths); |
| | | // this.path = path.filePaths; |
| | | }); |
| | | window.api.receive("selected-directory", (path) => { |
| | | console.log(path.filePaths); |
| | | }); |
| | | }, |
| | | initData() { |
| | | this.menuList.forEach((v) => { |
| | | v.visible = false; |
| | | v.disabled = this.disabledList.some((val) => val == v.id); |
| | | (v.children || []).forEach((item) => { |
| | | item.disabled = this.disabledList.some((val) => val == item.id); |
| | | }); |
| | | }); |
| | | console.log(this.menuList, this.disabledList, 9090) |
| | | }, |
| | | }, |
| | | |
| | | mounted() { |
| | | this.initData(); |
| | | this.initEvents(); |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .context-menu { |
| | | position: absolute; |
| | | background: #fff; |
| | | border: 1px #ccc solid; |
| | | border-radius: 4px; |
| | | padding: 4px; |
| | | .contain { |
| | | position: relative; |
| | | z-index: 100; |
| | | .main-ul { |
| | | display: flex; |
| | | flex-direction: column; |
| | | .main-li { |
| | | position: relative; |
| | | cursor: pointer; |
| | | flex: 1; |
| | | border: 1px #ccc solid; |
| | | padding: 4px; |
| | | &:hover { |
| | | background: #f0f0f0; |
| | | } |
| | | & ~ .main-li { |
| | | margin-top: 2px; |
| | | } |
| | | } |
| | | .sub-ul { |
| | | // display: none; |
| | | display: flex; |
| | | flex-direction: column; |
| | | position: absolute; |
| | | left: 100%; |
| | | top: 0; |
| | | transform: translateX(6px); |
| | | min-width: 10em; |
| | | background: #f0f0f0; |
| | | padding: 4px; |
| | | .sub-li { |
| | | border-radius: 4px; |
| | | border: 1px #333 solid; |
| | | background: #d9dce2; |
| | | &:hover { |
| | | background: #169bd5; |
| | | } |
| | | } |
| | | } |
| | | .disabled.disabled.disabled { |
| | | cursor: not-allowed; |
| | | color: #aaa; |
| | | background: #ccc; |
| | | } |
| | | } |
| | | } |
| | | .mask { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | top: 0; |
| | | bottom: 0; |
| | | background: transparent; |
| | | z-index: 99; |
| | | } |
| | | } |
| | | </style> |
New file |
| | |
| | | <template> |
| | | <div class="menu"> |
| | | <ul class="main-ul"> |
| | | <li class="main-li" v-for="(item, idx) in menuList" :key="'main_' + idx"> |
| | | <div |
| | | :class="['title', { active: item.active }]" |
| | | @click="clickMain(item)" |
| | | > |
| | | {{ item.title }} |
| | | </div> |
| | | <ul class="sub-ul" v-show="item.visible"> |
| | | <li |
| | | class="sub-li" |
| | | v-for="(subItem, index) in item.children" |
| | | :key="'sub_' + index" |
| | | @click="clickSub(subItem)" |
| | | > |
| | | {{ subItem.title }} |
| | | </li> |
| | | </ul> |
| | | </li> |
| | | </ul> |
| | | <!-- mask --> |
| | | <div class="mask" v-show="maskVisible" @click="closeMenu"></div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | name: "MenuList", |
| | | |
| | | data() { |
| | | const menuList = [ |
| | | { |
| | | title: "文件", |
| | | visible: false, |
| | | children: [ |
| | | { |
| | | title: "打开文件", |
| | | method: "openFile", |
| | | }, |
| | | { |
| | | title: "关闭文件", |
| | | method: "closeFile", |
| | | }, |
| | | { |
| | | title: "关闭所有文件", |
| | | method: "closeAllFiles", |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | title: "分析", |
| | | visible: false, |
| | | children: [ |
| | | { |
| | | title: "单数据分析", |
| | | }, |
| | | { |
| | | title: "对比分析", |
| | | }, |
| | | { |
| | | title: "分级评价", |
| | | }, |
| | | { |
| | | title: "生成报告", |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | title: "配置", |
| | | visible: false, |
| | | children: [ |
| | | { |
| | | title: "窗口配置", |
| | | }, |
| | | { |
| | | title: "数据管理", |
| | | }, |
| | | { |
| | | title: "语言设置", |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | title: "help", |
| | | visible: false, |
| | | children: [ |
| | | { |
| | | title: "说明书", |
| | | }, |
| | | { |
| | | title: "操作视频", |
| | | }, |
| | | { |
| | | title: "升级", |
| | | }, |
| | | { |
| | | title: "联系支持", |
| | | }, |
| | | { |
| | | title: "其它", |
| | | }, |
| | | ], |
| | | }, |
| | | ]; |
| | | return { |
| | | menuList, |
| | | maskVisible: false, |
| | | }; |
| | | }, |
| | | components: {}, |
| | | methods: { |
| | | clickMain(obj) { |
| | | // console.log(obj) |
| | | this.closeMenu(); |
| | | obj.visible = true; |
| | | obj.active = true; |
| | | this.maskVisible = true; |
| | | }, |
| | | clickSub(obj) { |
| | | // console.log(obj) |
| | | if (obj.method && "function" == typeof this[obj.method]) { |
| | | this.closeMenu(); |
| | | this[obj.method](); |
| | | } |
| | | }, |
| | | closeMenu() { |
| | | this.menuList.forEach((v) => { |
| | | v.visible = false; |
| | | v.active = false; |
| | | }); |
| | | this.maskVisible = false; |
| | | }, |
| | | openFile() { |
| | | // console.log("openfile"); |
| | | window.api.send("open-file-dialog"); |
| | | }, |
| | | initEvents() { |
| | | window.api.receive("selected-file", (path) => { |
| | | console.log(path.filePaths); |
| | | // this.path = path.filePaths; |
| | | }); |
| | | window.api.receive("selected-directory", (path) => { |
| | | console.log(path.filePaths); |
| | | }); |
| | | }, |
| | | }, |
| | | |
| | | mounted() { |
| | | this.initEvents(); |
| | | }, |
| | | }; |
| | | </script> |
| | | |
| | | <style lang="less" scoped> |
| | | .main-ul { |
| | | position: relative; |
| | | z-index: 1000; |
| | | display: flex; |
| | | align-items: stretch; |
| | | .main-li { |
| | | flex: 1; |
| | | position: relative; |
| | | .title { |
| | | cursor: pointer; |
| | | border: 1px solid #333; |
| | | background: #fbfbfb; |
| | | line-height: 30px; |
| | | border-radius: 4px; |
| | | vertical-align: middle; |
| | | &.active { |
| | | background: #169bd5; |
| | | } |
| | | &:hover { |
| | | background: #62cbfa; |
| | | } |
| | | } |
| | | } |
| | | .sub-ul { |
| | | // display: none; |
| | | display: flex; |
| | | flex-direction: column; |
| | | position: absolute; |
| | | left: 0; |
| | | top: 100%; |
| | | min-width: 8em; |
| | | background: #f0f0f0; |
| | | padding: 4px; |
| | | .sub-li { |
| | | border-radius: 4px; |
| | | border: 1px #333 solid; |
| | | background: #d9dce2; |
| | | &:hover { |
| | | background: #169bd5; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .mask { |
| | | position: fixed; |
| | | left: 0; |
| | | right: 0; |
| | | top: 0; |
| | | bottom: 0; |
| | | background: transparent; |
| | | z-index: 999; |
| | | } |
| | | </style> |
| | |
| | | import Vue from 'vue' |
| | | import App from './App.vue' |
| | | import router from './router' |
| | | import ElementUI from 'element-ui' |
| | | import 'element-ui/lib/theme-chalk/index.css' |
| | | |
| | | Vue.config.productionTip = false |
| | | |
| | | Vue.use(ElementUI, { |
| | | zIndex: 99 |
| | | }); |
| | | |
| | | new Vue({ |
| | | router, |
| | | render: h => h(App), |
| | | }).$mount('#app') |
New file |
| | |
| | | import { |
| | | contextBridge, |
| | | ipcRenderer |
| | | } from 'electron'; |
| | | |
| | | const validChannels = [ |
| | | 'renderer-ready', |
| | | 'main-window-ready', |
| | | 'open-file-dialog', |
| | | 'open-directory-dialog', |
| | | 'selected-directory', |
| | | 'selected-file' |
| | | ]; |
| | | |
| | | contextBridge.exposeInMainWorld('api', { |
| | | send: (channel, data) => { |
| | | if (validChannels.includes(channel)) { |
| | | ipcRenderer.send(channel, data); |
| | | } |
| | | }, |
| | | receive: (channel, func) => { |
| | | if (validChannels.includes(channel)) { |
| | | ipcRenderer.on(channel, (event, ...args) => { |
| | | func(...args) |
| | | }); |
| | | } |
| | | } |
| | | }); |
New file |
| | |
| | | import Vue from 'vue' |
| | | import Router from 'vue-router' |
| | | import routes from './routes' |
| | | |
| | | Vue.use(Router); |
| | | |
| | | const createRouter = () => new Router({ |
| | | // mode: 'history', // require service support |
| | | scrollBehavior: () => ({ |
| | | y: 0 |
| | | }), |
| | | routes |
| | | }) |
| | | |
| | | const router = createRouter() |
| | | |
| | | |
| | | export default router; |
New file |
| | |
| | | export default [{ |
| | | path: '/', |
| | | // redirect: '/selectFile' |
| | | }, |
| | | // 选文件页面 |
| | | // { |
| | | // path: '/selectFile', |
| | | // name: 'selectFile', |
| | | // meta: {}, |
| | | // component: () => import('@/views/selectFile') |
| | | // }, |
| | | |
| | | ]; |
New file |
| | |
| | | const path = require('path'); |
| | | |
| | | function resolve(dir) { |
| | | return path.join(__dirname, dir); |
| | | } |
| | | |
| | | module.exports = { |
| | | publicPath: './', |
| | | devServer: { |
| | | // can be overwritten by process.env.HOST |
| | | host: '0.0.0.0', |
| | | port: 8081 |
| | | }, |
| | | pluginOptions:{ |
| | | electronBuilder:{ |
| | | preload:'src/preload.js', |
| | | builderOptions: { |
| | | extraResources: [ |
| | | { |
| | | from: "./public/runtime", |
| | | to: "./runtime" |
| | | }, |
| | | { |
| | | from: "./public/app_x64.exe", |
| | | to: "./app_x64.exe" |
| | | } |
| | | ], |
| | | files: [ |
| | | '**/*', |
| | | '!**/runtime', |
| | | '!**/app_x64.exe' |
| | | ], |
| | | } |
| | | } |
| | | }, |
| | | chainWebpack: config => { |
| | | config.resolve.alias |
| | | .set('@', resolve('src')) |
| | | .set('src', resolve('src')) |
| | | .set('common', resolve('src/common')) |
| | | .set('components', resolve('src/components')); |
| | | |
| | | config.plugin('html').tap((args) => { |
| | | args[0].title = '内阻测试分析软件V1.1.1'; |
| | | return args; |
| | | }) |
| | | } |
| | | }; |