commit
e89e7150eb
27 changed files with 1264 additions and 0 deletions
@ -0,0 +1,9 @@ |
|||||
|
root = true |
||||
|
|
||||
|
[*] |
||||
|
charset = utf-8 |
||||
|
indent_style = space |
||||
|
indent_size = 2 |
||||
|
end_of_line = lf |
||||
|
insert_final_newline = true |
||||
|
trim_trailing_whitespace = true |
@ -0,0 +1,5 @@ |
|||||
|
node_modules |
||||
|
dist |
||||
|
out |
||||
|
*.log* |
||||
|
package-lock.json |
@ -0,0 +1 @@ |
|||||
|
ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ |
@ -0,0 +1,6 @@ |
|||||
|
out |
||||
|
dist |
||||
|
pnpm-lock.yaml |
||||
|
LICENSE.md |
||||
|
tsconfig.json |
||||
|
tsconfig.*.json |
@ -0,0 +1,6 @@ |
|||||
|
{ |
||||
|
"singleQuote": true, |
||||
|
"semi": false, |
||||
|
"printWidth": 100, |
||||
|
"trailingComma": "none" |
||||
|
} |
@ -0,0 +1,34 @@ |
|||||
|
# my-app |
||||
|
|
||||
|
An Electron application with Vue |
||||
|
|
||||
|
## Recommended IDE Setup |
||||
|
|
||||
|
- [VSCode](https://code.visualstudio.com/) + [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) + [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) |
||||
|
|
||||
|
## Project Setup |
||||
|
|
||||
|
### Install(node 16.20.1) |
||||
|
|
||||
|
```bash |
||||
|
$ npm install |
||||
|
``` |
||||
|
|
||||
|
### Development |
||||
|
|
||||
|
```bash |
||||
|
$ npm run dev |
||||
|
``` |
||||
|
|
||||
|
### Build |
||||
|
|
||||
|
```bash |
||||
|
# For windows |
||||
|
$ npm run build:win |
||||
|
|
||||
|
# For macOS |
||||
|
$ npm run build:mac |
||||
|
|
||||
|
# For Linux |
||||
|
$ npm run build:linux |
||||
|
``` |
@ -0,0 +1,12 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
||||
|
<plist version="1.0"> |
||||
|
<dict> |
||||
|
<key>com.apple.security.cs.allow-jit</key> |
||||
|
<true/> |
||||
|
<key>com.apple.security.cs.allow-unsigned-executable-memory</key> |
||||
|
<true/> |
||||
|
<key>com.apple.security.cs.allow-dyld-environment-variables</key> |
||||
|
<true/> |
||||
|
</dict> |
||||
|
</plist> |
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
@ -0,0 +1,36 @@ |
|||||
|
const { notarize } = require('electron-notarize') |
||||
|
|
||||
|
module.exports = async (context) => { |
||||
|
if (process.platform !== 'darwin') return |
||||
|
|
||||
|
console.log('aftersign hook triggered, start to notarize app.') |
||||
|
|
||||
|
if (!process.env.CI) { |
||||
|
console.log(`skipping notarizing, not in CI.`) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
if (!('APPLE_ID' in process.env && 'APPLE_ID_PASS' in process.env)) { |
||||
|
console.warn('skipping notarizing, APPLE_ID and APPLE_ID_PASS env variables must be set.') |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
const appId = 'com.electron.app' |
||||
|
|
||||
|
const { appOutDir } = context |
||||
|
|
||||
|
const appName = context.packager.appInfo.productFilename |
||||
|
|
||||
|
try { |
||||
|
await notarize({ |
||||
|
appBundleId: appId, |
||||
|
appPath: `${appOutDir}/${appName}.app`, |
||||
|
appleId: process.env.APPLE_ID, |
||||
|
appleIdPassword: process.env.APPLEIDPASS |
||||
|
}) |
||||
|
} catch (error) { |
||||
|
console.error(error) |
||||
|
} |
||||
|
|
||||
|
console.log(`done notarizing ${appId}.`) |
||||
|
} |
@ -0,0 +1,43 @@ |
|||||
|
appId: com.electron.lichong |
||||
|
productName: 我的钢铁网取价 |
||||
|
directories: |
||||
|
buildResources: build |
||||
|
files: |
||||
|
- '!**/.vscode/*' |
||||
|
- '!src/*' |
||||
|
- '!electron.vite.config.{js,ts,mjs,cjs}' |
||||
|
- '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}' |
||||
|
asarUnpack: |
||||
|
- '**/*.{node,dll}' |
||||
|
afterSign: build/notarize.js |
||||
|
win: |
||||
|
executableName: lichong-app |
||||
|
nsis: |
||||
|
oneClick: false |
||||
|
artifactName: 我的钢铁网取价-${version}-setup.${ext} |
||||
|
allowToChangeInstallationDirectory: true |
||||
|
shortcutName: ${productName} |
||||
|
uninstallDisplayName: ${productName} |
||||
|
createDesktopShortcut: always |
||||
|
mac: |
||||
|
entitlementsInherit: build/entitlements.mac.plist |
||||
|
extendInfo: |
||||
|
- NSCameraUsageDescription: Application requests access to the device's camera. |
||||
|
- NSMicrophoneUsageDescription: Application requests access to the device's microphone. |
||||
|
- NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder. |
||||
|
- NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder. |
||||
|
dmg: |
||||
|
artifactName: ${name}-${version}.${ext} |
||||
|
linux: |
||||
|
target: |
||||
|
- AppImage |
||||
|
- snap |
||||
|
- deb |
||||
|
maintainer: electronjs.org |
||||
|
category: Utility |
||||
|
appImage: |
||||
|
artifactName: ${name}-${version}.${ext} |
||||
|
npmRebuild: false |
||||
|
publish: |
||||
|
provider: generic |
||||
|
url: https://example.com/auto-updates |
@ -0,0 +1,28 @@ |
|||||
|
import { resolve } from 'path' |
||||
|
import { defineConfig, externalizeDepsPlugin } from 'electron-vite' |
||||
|
import vue from '@vitejs/plugin-vue' |
||||
|
|
||||
|
export default defineConfig({ |
||||
|
main: { |
||||
|
plugins: [externalizeDepsPlugin()] |
||||
|
}, |
||||
|
preload: { |
||||
|
plugins: [externalizeDepsPlugin()], |
||||
|
build: { |
||||
|
rollupOptions: { |
||||
|
input: { |
||||
|
dl: resolve(__dirname, 'src/preload/dl.js'), |
||||
|
index: resolve(__dirname, 'src/preload/index.js') |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
renderer: { |
||||
|
resolve: { |
||||
|
alias: { |
||||
|
'@renderer': resolve('src/renderer/src') |
||||
|
} |
||||
|
}, |
||||
|
plugins: [vue()] |
||||
|
} |
||||
|
}) |
@ -0,0 +1,6 @@ |
|||||
|
{ |
||||
|
"exclude": [ |
||||
|
"node_modules", |
||||
|
"public" |
||||
|
] |
||||
|
} |
@ -0,0 +1,41 @@ |
|||||
|
{ |
||||
|
"name": "electron", |
||||
|
"version": "1.0.1", |
||||
|
"description": "An Electron application with Vue", |
||||
|
"main": "./out/main/index.js", |
||||
|
"author": "lichong", |
||||
|
"homepage": "https://www.electronjs.org", |
||||
|
"scripts": { |
||||
|
"npmi": "npm i", |
||||
|
"dev": "electron-vite dev", |
||||
|
"build": "electron-vite build", |
||||
|
"build:win": "npm run build && electron-builder --win --config", |
||||
|
"build:mac": "npm run build && electron-builder --mac --config", |
||||
|
"build:linux": "npm run build && electron-builder --linux --config" |
||||
|
}, |
||||
|
"dependencies": { |
||||
|
"@electron-toolkit/preload": "^1.0.2", |
||||
|
"@electron-toolkit/utils": "^1.0.2", |
||||
|
"dayjs": "^1.11.11", |
||||
|
"dexie": "^4.0.8", |
||||
|
"element-plus": "^2.7.1", |
||||
|
"htmlparser2": "^9.1.0", |
||||
|
"lodash": "^4.17.21", |
||||
|
"tabletojson": "^4.1.4", |
||||
|
"vxe-table": "^4.7.87", |
||||
|
"xlsx": "^0.18.5" |
||||
|
}, |
||||
|
"devDependencies": { |
||||
|
"@rushstack/eslint-patch": "^1.2.0", |
||||
|
"@vitejs/plugin-vue": "^3.1.2", |
||||
|
"@vue/eslint-config-prettier": "^7.0.0", |
||||
|
"electron": "^20.3.2", |
||||
|
"electron-builder": "^23.6.0", |
||||
|
"electron-notarize": "^1.2.1", |
||||
|
"electron-vite": "^1.0.11", |
||||
|
"less": "^4.1.3", |
||||
|
"prettier": "^2.7.1", |
||||
|
"vite": "^3.1.8", |
||||
|
"vue": "^3.2.41" |
||||
|
} |
||||
|
} |
After Width: | Height: | Size: 16 KiB |
@ -0,0 +1,71 @@ |
|||||
|
import { app, shell, BrowserWindow, nativeImage } from 'electron' |
||||
|
import * as path from 'path' |
||||
|
import { electronApp, optimizer, is } from '@electron-toolkit/utils' |
||||
|
|
||||
|
// logo
|
||||
|
const logoIcon = nativeImage.createFromPath(path.join(__dirname, '../../public/icon/icon.jpg')) |
||||
|
// 主窗口
|
||||
|
let mainWindow |
||||
|
function createWindow() { |
||||
|
mainWindow = new BrowserWindow({ |
||||
|
minWidth: 1366, |
||||
|
minHeight: 900, |
||||
|
height: 1260, |
||||
|
width: 1730, |
||||
|
show: false, |
||||
|
autoHideMenuBar: true, |
||||
|
icon: logoIcon, |
||||
|
webPreferences: { |
||||
|
preload: path.resolve(__dirname, '../preload/index.js'), |
||||
|
sandbox: false, |
||||
|
nodeIntegration: true, |
||||
|
contextIsolation: false |
||||
|
} |
||||
|
}) |
||||
|
mainWindow.on('ready-to-show', () => { |
||||
|
mainWindow.show() |
||||
|
// mainWindow.webContents.openDevTools()
|
||||
|
}) |
||||
|
mainWindow.webContents.setWindowOpenHandler((details) => { |
||||
|
shell.openExternal(details.url) |
||||
|
return { action: 'deny' } |
||||
|
}) |
||||
|
// mainWindow.loadURL('http://localhost:5173/')
|
||||
|
|
||||
|
mainWindow.on('close', () => { |
||||
|
app.exit() |
||||
|
}) |
||||
|
if (is.dev && process.env['ELECTRON_RENDERER_URL']) { |
||||
|
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL']) |
||||
|
} else { |
||||
|
mainWindow.loadFile(path.join(__dirname, '../renderer/index.html')) |
||||
|
} |
||||
|
} |
||||
|
app.whenReady().then(() => { |
||||
|
electronApp.setAppUserModelId('com.electron') |
||||
|
// Default open or close DevTools by F12 in development
|
||||
|
// and ignore CommandOrControl + R in production.
|
||||
|
// see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
|
||||
|
app.on('browser-window-created', (_, window) => { |
||||
|
optimizer.watchWindowShortcuts(window) |
||||
|
}) |
||||
|
|
||||
|
createWindow() |
||||
|
|
||||
|
app.on('activate', function () { |
||||
|
// 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() |
||||
|
}) |
||||
|
}) |
||||
|
app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required'); |
||||
|
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
|
// for applications and their menu bar to stay active until the user quits
|
||||
|
// explicitly with Cmd + Q.
|
||||
|
app.on('window-all-closed', () => { |
||||
|
if (process.platform !== 'darwin') { |
||||
|
app.quit() |
||||
|
} |
||||
|
}) |
||||
|
// In this file you can include the rest of your app"s specific main process
|
||||
|
// code. You can also put them in separate files and require them here.
|
@ -0,0 +1,21 @@ |
|||||
|
import { contextBridge, clipboard } from 'electron' |
||||
|
import { electronAPI } from '@electron-toolkit/preload' |
||||
|
|
||||
|
// Custom APIs for renderer
|
||||
|
const api = {} |
||||
|
|
||||
|
// Use `contextBridge` APIs to expose Electron APIs to
|
||||
|
// renderer only if context isolation is enabled, otherwise
|
||||
|
// just add to the DOM global.
|
||||
|
if (process.contextIsolated) { |
||||
|
try { |
||||
|
contextBridge.exposeInMainWorld('electron', electronAPI) |
||||
|
contextBridge.exposeInMainWorld('api', api) |
||||
|
contextBridge.exposeInMainWorld('elecClipboard', clipboard) |
||||
|
} catch (error) { |
||||
|
console.error(error) |
||||
|
} |
||||
|
} else { |
||||
|
window.electron = electronAPI |
||||
|
window.api = api |
||||
|
} |
@ -0,0 +1,21 @@ |
|||||
|
import { contextBridge, clipboard } from 'electron' |
||||
|
import { electronAPI } from '@electron-toolkit/preload' |
||||
|
|
||||
|
// Custom APIs for renderer
|
||||
|
const api = {} |
||||
|
|
||||
|
// Use `contextBridge` APIs to expose Electron APIs to
|
||||
|
// renderer only if context isolation is enabled, otherwise
|
||||
|
// just add to the DOM global.
|
||||
|
if (process.contextIsolated) { |
||||
|
try { |
||||
|
contextBridge.exposeInMainWorld('electron', electronAPI) |
||||
|
contextBridge.exposeInMainWorld('api', api) |
||||
|
contextBridge.exposeInMainWorld('elecClipboard', clipboard) |
||||
|
} catch (error) { |
||||
|
console.error(error) |
||||
|
} |
||||
|
} else { |
||||
|
window.electron = electronAPI |
||||
|
window.api = api |
||||
|
} |
@ -0,0 +1,18 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="UTF-8" /> |
||||
|
<title>我的钢铁网取价</title> |
||||
|
<!-- <link rel="icon" href="/icon/icon.jpg" /> --> |
||||
|
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> |
||||
|
<meta http-equiv="Content-Security-Policy" |
||||
|
content="default-src 'self'; script-src 'self';img-src 'self' data:; style-src 'self' 'unsafe-inline';font-src 'self' data:;" /> |
||||
|
</head> |
||||
|
|
||||
|
<body> |
||||
|
<div id="app"></div> |
||||
|
<script type="module" src="/src/main.js"></script> |
||||
|
</body> |
||||
|
|
||||
|
</html> |
@ -0,0 +1,65 @@ |
|||||
|
<template> |
||||
|
<div class="appClass" v-if="isVip"> |
||||
|
<jiageComponent ref="jiage"> </jiageComponent> |
||||
|
</div> |
||||
|
<div v-else class="noVip"> |
||||
|
<h3> |
||||
|
<el-tag type="danger" class="noVipTag">体验已过期,请联系管理员。</el-tag> |
||||
|
</h3> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import _ from 'lodash' |
||||
|
import dayjs from 'dayjs' |
||||
|
import { myDatabase } from './assets/js/db.js' |
||||
|
import jiageComponent from "./views/jiage.vue" |
||||
|
import { ElMessage } from 'element-plus'; |
||||
|
export default { |
||||
|
name: 'app', |
||||
|
components: { jiageComponent }, |
||||
|
data() { |
||||
|
return { |
||||
|
_: _, |
||||
|
dayjs: dayjs, |
||||
|
isVip: true, |
||||
|
jihuoma: "", |
||||
|
zhucema: "", |
||||
|
} |
||||
|
}, |
||||
|
watch: {}, |
||||
|
computed: {}, |
||||
|
methods: { |
||||
|
}, |
||||
|
async mounted() { |
||||
|
let fiveDay = dayjs('2024-11-7T00:00:00').valueOf() |
||||
|
if (!this.isVip) { |
||||
|
if (dayjs().valueOf() > fiveDay) { |
||||
|
this.isVip = false |
||||
|
return |
||||
|
} else { |
||||
|
this.isVip = true |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
} |
||||
|
</script> |
||||
|
<style scoped> |
||||
|
.appClass { |
||||
|
width: 100vw; |
||||
|
height: 100vh; |
||||
|
position: relative; |
||||
|
} |
||||
|
|
||||
|
.noVip { |
||||
|
text-align: center; |
||||
|
margin-top: calc(50vh - 98px); |
||||
|
} |
||||
|
|
||||
|
.noVipTag { |
||||
|
font-size: 48px; |
||||
|
line-height: 48px; |
||||
|
padding: 36px; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,13 @@ |
|||||
|
html, |
||||
|
body { |
||||
|
margin: 0; |
||||
|
padding: 0; |
||||
|
} |
||||
|
|
||||
|
.red { |
||||
|
color: #f56c6c; |
||||
|
} |
||||
|
|
||||
|
.blue { |
||||
|
color: #409eff; |
||||
|
} |
@ -0,0 +1,8 @@ |
|||||
|
import Dexie from 'dexie'; |
||||
|
|
||||
|
export const myDatabase = new Dexie('myDatabase'); |
||||
|
|
||||
|
// 定义数据库版本
|
||||
|
myDatabase.version(1).stores({ |
||||
|
jiage: '++id, date, pinming, guige, caizhi, chandi, ¬e, jiage,create_at, update_at', |
||||
|
}); |
@ -0,0 +1,66 @@ |
|||||
|
[ |
||||
|
{ |
||||
|
"label": "日期", |
||||
|
"prop": "date", |
||||
|
"type": "text", |
||||
|
"isSort": false, |
||||
|
"tableShow": true, |
||||
|
"formShow": true |
||||
|
}, |
||||
|
{ |
||||
|
"label": "品名", |
||||
|
"prop": "pinming", |
||||
|
"type": "text", |
||||
|
"isSort": false, |
||||
|
"tableShow": true, |
||||
|
"formShow": true |
||||
|
}, |
||||
|
{ |
||||
|
"label": "规格", |
||||
|
"prop": "guige", |
||||
|
"type": "text", |
||||
|
"isSort": false, |
||||
|
"tableShow": true, |
||||
|
"formShow": true |
||||
|
}, |
||||
|
{ |
||||
|
"label": "材质", |
||||
|
"prop": "caizhi", |
||||
|
"type": "text", |
||||
|
"isSort": false, |
||||
|
"tableShow": true, |
||||
|
"formShow": true |
||||
|
}, |
||||
|
{ |
||||
|
"label": "产地", |
||||
|
"prop": "chandi", |
||||
|
"type": "text", |
||||
|
"isSort": false, |
||||
|
"tableShow": true, |
||||
|
"formShow": true |
||||
|
}, |
||||
|
{ |
||||
|
"label": "价格", |
||||
|
"prop": "jiage", |
||||
|
"type": "text", |
||||
|
"isSort": false, |
||||
|
"tableShow": true, |
||||
|
"formShow": true |
||||
|
}, |
||||
|
{ |
||||
|
"label": "创建时间", |
||||
|
"prop": "create_at", |
||||
|
"type": "date", |
||||
|
"isSort": false, |
||||
|
"tableShow": false, |
||||
|
"formShow": false |
||||
|
}, |
||||
|
{ |
||||
|
"label": "更新时间", |
||||
|
"prop": "update_at", |
||||
|
"type": "date", |
||||
|
"isSort": false, |
||||
|
"tableShow": false, |
||||
|
"formShow": false |
||||
|
} |
||||
|
] |
@ -0,0 +1,119 @@ |
|||||
|
<template> |
||||
|
<div class="tableClass"> |
||||
|
<el-form :model="formData" label-suffix=":" :disabled="disabled" @submit.prevent> |
||||
|
<el-row> |
||||
|
<el-col :key="formIndex" v-for="(formItem, formIndex) in formHeader" |
||||
|
:span="['text', 'date', 'textarea'].includes(formItem.type) ? 24 : 12"> |
||||
|
<el-form-item :label="formItem.label"> |
||||
|
<template v-if="['text', 'textarea'].includes(formItem.type)"> |
||||
|
<el-input v-model="formData[formItem.prop]" :type="formItem.type" style="width: 80%;" /> |
||||
|
</template> |
||||
|
<template v-else-if="formItem.type === 'date'"> |
||||
|
<el-date-picker v-model="formData[formItem.prop]" type="date" |
||||
|
:disabled="['create_at', 'update_at'].indexOf(formItem.prop) !== -1" |
||||
|
:placeholder="`请选择${formItem.label}`" /> |
||||
|
</template> |
||||
|
</el-form-item> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
</el-form> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import _, { max, min } from 'lodash' |
||||
|
import dayjs from 'dayjs' |
||||
|
import { ElMessage, ElMessageBox } from 'element-plus' |
||||
|
export default { |
||||
|
name: 'formcomponent', |
||||
|
components: {}, |
||||
|
props: { |
||||
|
formHeader: { |
||||
|
type: Array, |
||||
|
default: () => { |
||||
|
return [] |
||||
|
} |
||||
|
}, |
||||
|
formData: { |
||||
|
type: Object, |
||||
|
default: () => { |
||||
|
return {} |
||||
|
} |
||||
|
}, |
||||
|
disabled: { |
||||
|
type: Boolean, |
||||
|
default: () => { |
||||
|
return false |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
_: _, |
||||
|
dayjs: dayjs, |
||||
|
width: 569, |
||||
|
height: 320, |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
async openVedio(formItem) { |
||||
|
let that = this |
||||
|
try { |
||||
|
this.formData[formItem.prop] = "" |
||||
|
let stream = await navigator.mediaDevices.getUserMedia({ |
||||
|
video: { |
||||
|
width: { ideal: that.width }, |
||||
|
height: { ideal: that.height } |
||||
|
}, |
||||
|
}); |
||||
|
this.$refs[`${formItem.prop}video`][0].srcObject = stream; |
||||
|
} catch (e) { |
||||
|
ElMessage({ |
||||
|
type: 'error', |
||||
|
message: '摄像头权限被禁止,请打开摄像头权限', |
||||
|
}) |
||||
|
return |
||||
|
} |
||||
|
}, |
||||
|
takePhoto(formItem) { |
||||
|
let that = this |
||||
|
let video = this.$refs[`${formItem.prop}video`][0] |
||||
|
let canvas = this.$refs[`${formItem.prop}canvas`][0] |
||||
|
let context = canvas.getContext('2d'); |
||||
|
context.drawImage(video, 0, 0, that.width, that.height); |
||||
|
this.formData[formItem.prop] = canvas.toDataURL('image/png'); |
||||
|
}, |
||||
|
// 聚焦 |
||||
|
focus(formItem) { |
||||
|
if (_.get(this.$refs[`${formItem.prop}video`], [0, "srcObject"], "")) { |
||||
|
let tracks = this.$refs[`${formItem.prop}video`][0].srcObject.getVideoTracks() |
||||
|
tracks.forEach(track => { |
||||
|
if (track.getCapabilities().focusMode && track.getCapabilities().focusMode.includes('continuous')) { |
||||
|
track.applyConstraints({ advanced: [{ focusMode: 'continuous' }] }); |
||||
|
} else { |
||||
|
ElMessage({ |
||||
|
type: 'error', |
||||
|
message: '摄像头不支持连续聚焦模式。', |
||||
|
}) |
||||
|
} |
||||
|
}); |
||||
|
} else { |
||||
|
ElMessage({ |
||||
|
type: 'error', |
||||
|
message: '摄像头不支持连续聚焦模式。', |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
async mounted() { }, |
||||
|
watch: {}, |
||||
|
computed: {} |
||||
|
} |
||||
|
</script> |
||||
|
<style scoped> |
||||
|
.tableClass { |
||||
|
text-align: left; |
||||
|
text-align-last: left; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,138 @@ |
|||||
|
<template> |
||||
|
<div class="tableClass"> |
||||
|
<el-auto-resizer> |
||||
|
<template #default="{ height, width }"> |
||||
|
<vxe-table show-overflow :data="tableData" round :height="height" :scroll-y="{ enabled: true, gt: 20 }" |
||||
|
:checkbox-config="{ labelField: 'seq', highlight: true }" @checkbox-all="selectAllChangeEvent" |
||||
|
@checkbox-change="selectChange" ref="tableRef" border :column-config="{ resizable: true }"> |
||||
|
<vxe-column type="seq" width="70"></vxe-column> |
||||
|
<vxe-column type="checkbox" width="60"></vxe-column> |
||||
|
<vxe-column :field="headerItem.prop" :title="headerItem.label" |
||||
|
:min-width="`${headerItem.label.length * 23 + 24}`" v-for="(headerItem, headerIndex) in tableHeader" |
||||
|
:key="headerIndex" :sortable="headerItem.isSort"> |
||||
|
<template #default="{ row }"> |
||||
|
<template v-if="headerItem.type === 'text'"> |
||||
|
<span>{{ row[headerItem.prop] }}</span> |
||||
|
</template> |
||||
|
<template v-else-if="headerItem.type === 'date'"> |
||||
|
<span>{{ dayjs(row[headerItem.prop]).format("YYYY-MM-DD HH:mm:ss") }}</span> |
||||
|
</template> |
||||
|
<template v-else-if="headerItem.type === 'photo'"> |
||||
|
<span v-if="row[headerItem.prop]"> |
||||
|
<el-image style="width: 45px" :src="row[headerItem.prop]" :zoom-rate="1.2" :max-scale="7" |
||||
|
:min-scale="0.2" :preview-src-list="[row[headerItem.prop]]" :initial-index="4" fit="cover" /> |
||||
|
</span> |
||||
|
<span v-else>无</span> |
||||
|
</template> |
||||
|
<template v-else>{{ row[headerItem.prop] }}</template> |
||||
|
</template> |
||||
|
</vxe-column> |
||||
|
<vxe-column title="操作" width="145"> |
||||
|
<template #default="{ row }"> |
||||
|
<el-button type="primary" circle @click="optClick(row, 'edit')"> |
||||
|
<el-icon> |
||||
|
<Edit /> |
||||
|
</el-icon> |
||||
|
</el-button> |
||||
|
<el-button type="info" circle @click="optClick(row, 'info')"> |
||||
|
<el-icon> |
||||
|
<InfoFilled /> |
||||
|
</el-icon> |
||||
|
</el-button> |
||||
|
<el-button type="danger" circle @click="optClick(row, 'del')"> |
||||
|
<el-icon> |
||||
|
<Delete /> |
||||
|
</el-icon> |
||||
|
</el-button> |
||||
|
</template> |
||||
|
</vxe-column> |
||||
|
</vxe-table> |
||||
|
</template> |
||||
|
</el-auto-resizer> |
||||
|
|
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import _ from 'lodash' |
||||
|
import dayjs from 'dayjs' |
||||
|
import { ElMessage, ElMessageBox } from 'element-plus' |
||||
|
export default { |
||||
|
name: 'tablecomponent', |
||||
|
components: {}, |
||||
|
emits: ["selectChange", "edit", "info", "del", "headerSort"], |
||||
|
props: { |
||||
|
tableHeader: { |
||||
|
type: Array, |
||||
|
default: () => { |
||||
|
return [] |
||||
|
} |
||||
|
}, |
||||
|
tableData: { |
||||
|
type: Array, |
||||
|
default: () => { |
||||
|
return [] |
||||
|
} |
||||
|
}, |
||||
|
}, |
||||
|
data() { |
||||
|
return { |
||||
|
_: _, |
||||
|
dayjs: dayjs, |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
clearSelection() { |
||||
|
const $table = this.$refs.tableRef |
||||
|
if ($table) { |
||||
|
$table.clearCheckboxRow() |
||||
|
} |
||||
|
}, |
||||
|
selectChange({ checked }) { |
||||
|
let $table = this.$refs.tableRef |
||||
|
if ($table) { |
||||
|
let selection = $table.getCheckboxRecords() |
||||
|
this.$emit("selectChange", selection) |
||||
|
} |
||||
|
}, |
||||
|
selectAllChangeEvent({ checked }) { |
||||
|
let $table = this.$refs.tableRef |
||||
|
if ($table) { |
||||
|
let selection = $table.getCheckboxRecords() |
||||
|
this.$emit("selectChange", selection) |
||||
|
} |
||||
|
}, |
||||
|
optClick(row, type) { |
||||
|
this.$emit(type, row) |
||||
|
}, |
||||
|
headerSort(headerItem) { |
||||
|
for (let i = 0; i < this.tableHeader.length; i++) { |
||||
|
let item = this.tableHeader[i]; |
||||
|
if (headerItem.prop !== item.prop) { |
||||
|
item.sort = "" |
||||
|
} |
||||
|
} |
||||
|
let sortOld = headerItem.sort |
||||
|
if (sortOld === "") { |
||||
|
headerItem.sort = 1 |
||||
|
} else if (sortOld === 1) { |
||||
|
headerItem.sort = -1 |
||||
|
} else if (sortOld === -1) { |
||||
|
headerItem.sort = "" |
||||
|
} |
||||
|
|
||||
|
this.$emit("headerSort", headerItem) |
||||
|
}, |
||||
|
}, |
||||
|
async mounted() { }, |
||||
|
watch: {}, |
||||
|
computed: {} |
||||
|
} |
||||
|
</script> |
||||
|
<style scoped> |
||||
|
.tableClass { |
||||
|
height: calc(100vh - 70px); |
||||
|
text-align: center; |
||||
|
text-align-last: center; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,33 @@ |
|||||
|
// main.ts
|
||||
|
import { createApp } from 'vue' |
||||
|
import ElementPlus from 'element-plus' |
||||
|
import zhCn from 'element-plus/es/locale/lang/zh-cn' |
||||
|
import 'element-plus/dist/index.css' |
||||
|
import App from './App.vue' |
||||
|
import './assets/css/base.css' |
||||
|
import * as ElementPlusIconsVue from '@element-plus/icons-vue' |
||||
|
import VxeUI from 'vxe-pc-ui' |
||||
|
import 'vxe-pc-ui/lib/style.css' |
||||
|
// ...
|
||||
|
|
||||
|
// 完整导入 表格库
|
||||
|
import VxeUITable from 'vxe-table' |
||||
|
import 'vxe-table/lib/style.css' |
||||
|
|
||||
|
const app = createApp(App) |
||||
|
// window.__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ = true
|
||||
|
for (const [key, component] of Object.entries(ElementPlusIconsVue)) { |
||||
|
app.component(key, component) |
||||
|
} |
||||
|
app.use(ElementPlus, { |
||||
|
locale: zhCn, |
||||
|
}) |
||||
|
app.use(VxeUI).use(VxeUITable) |
||||
|
app.mount('#app') |
||||
|
|
||||
|
document.addEventListener('keydown', (event) => { |
||||
|
const { ctrlKey, shiftKey, key } = event |
||||
|
if ((ctrlKey && shiftKey && key === 'I') || key === 'F12') { |
||||
|
return event.preventDefault() |
||||
|
} |
||||
|
}) |
@ -0,0 +1,464 @@ |
|||||
|
<template> |
||||
|
<div class="rightClass"> |
||||
|
<div> |
||||
|
<el-row style="margin-bottom: 8px;"> |
||||
|
<el-col :span="16"> |
||||
|
<el-button type="primary" @click="addData" size="large" class="inputClass"> |
||||
|
<el-icon> |
||||
|
<Plus /> |
||||
|
</el-icon> |
||||
|
<span>新增</span> |
||||
|
</el-button> |
||||
|
<el-button type="danger" @click="deleteData(selectionData)" :disabled="selectionData.length == 0" size="large" |
||||
|
class="inputClass"> |
||||
|
<el-icon> |
||||
|
<Delete /> |
||||
|
</el-icon> |
||||
|
<span>删除</span> |
||||
|
</el-button> |
||||
|
<el-button type="danger" @click="delAll" size="large" class="inputClass"> |
||||
|
<el-icon> |
||||
|
<Delete /> |
||||
|
</el-icon> |
||||
|
<span>清空</span> |
||||
|
</el-button> |
||||
|
<el-upload :show-file-list="false" v-model="fileOriData" :before-upload="beforeAvatarUpload" |
||||
|
:http-request="successSubmit" accept=".xls,.xlsx,.csv" |
||||
|
style="display: inline-block;position: relative;top: 3px;"> |
||||
|
<el-button type="success" size="large" class="inputClass"> |
||||
|
<el-icon> |
||||
|
<Upload /> |
||||
|
</el-icon> |
||||
|
<span>上传表格</span> |
||||
|
</el-button> |
||||
|
</el-upload> |
||||
|
<el-button type="primary" @click="downExcel" size="large" class="inputClass" :disabled="fileList.length === 0"> |
||||
|
<el-icon> |
||||
|
<Download /> |
||||
|
</el-icon> |
||||
|
<span>下载转换后的表格</span> |
||||
|
</el-button> |
||||
|
<el-button type="primary" @click="exportAllData" size="large" class="inputClass" |
||||
|
:disabled="tableData.length === 0"> |
||||
|
<el-icon> |
||||
|
<Download /> |
||||
|
</el-icon> |
||||
|
<span>导出表格内的数据</span> |
||||
|
</el-button> |
||||
|
</el-col> |
||||
|
</el-row> |
||||
|
</div> |
||||
|
<div v-loading="loading"> |
||||
|
<tablecomponent :tableHeader="tableHeader" :tableData="tableData" @selectChange="selectChange" @edit="edit" |
||||
|
@info="info" @del="del" ref="tableComponentRef" @headerSort="headerSort"> |
||||
|
</tablecomponent> |
||||
|
</div> |
||||
|
<el-dialog v-model="dialogFrom.visible" :title="dialogFrom.title" width="80%" :close-on-click-modal="false"> |
||||
|
<formcomponent :formHeader="dialogFrom.formHeader" :formData="dialogFrom.formData" |
||||
|
:disabled="dialogFrom.disabled"> |
||||
|
</formcomponent> |
||||
|
<template #footer> |
||||
|
<div> |
||||
|
<el-button @click="cancelDialog">取消</el-button> |
||||
|
<el-button type="primary" @click="submitDialog"> 确认 </el-button> |
||||
|
</div> |
||||
|
</template> |
||||
|
</el-dialog> |
||||
|
<el-dialog v-model="addDataVisible" title="新增数据" width="80%" :close-on-click-modal="false"> |
||||
|
<el-form :model="form" @submit.prevent label-width="auto"> |
||||
|
<el-form-item prop="jiageDate" label="日期" :rules="[ |
||||
|
{ required: true, message: '日期 is required' }, |
||||
|
]"> |
||||
|
<el-date-picker v-model="form.jiageDate" type="date" placeholder="请选择日期" size="large" |
||||
|
value-format="YYYY-MM-DD" /> |
||||
|
</el-form-item> |
||||
|
<el-form-item prop="jiageStr" label="表格元素" :rules="[ |
||||
|
{ required: true, message: '表格元素 is required' }, |
||||
|
]"> |
||||
|
<el-input v-model="form.jiageStr" :autosize="{ minRows: 5, maxRows: 20 }" type="textarea" |
||||
|
placeholder="请输入表格元素" size="large" /> |
||||
|
</el-form-item> |
||||
|
</el-form> |
||||
|
|
||||
|
|
||||
|
<template #footer> |
||||
|
<div> |
||||
|
<el-button @click="cancelData">取消</el-button> |
||||
|
<el-button type="primary" @click="submitAddData"> 确认 </el-button> |
||||
|
</div> |
||||
|
</template> |
||||
|
</el-dialog> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script> |
||||
|
import _ from 'lodash' |
||||
|
import * as XLSX from 'xlsx'; |
||||
|
import { tabletojson } from "tabletojson"; |
||||
|
import tableHeaderLocal from '../assets/json/jiage.json' |
||||
|
import { myDatabase } from '../assets/js/db.js' |
||||
|
import dayjs from 'dayjs' |
||||
|
import tablecomponent from "../components/tablecomponent.vue" |
||||
|
import formcomponent from "../components/formcomponent.vue" |
||||
|
import { ElMessage, ElMessageBox } from 'element-plus' |
||||
|
export default { |
||||
|
name: 'jiage', |
||||
|
components: { tablecomponent, formcomponent }, |
||||
|
watch: {}, |
||||
|
computed: {}, |
||||
|
data() { |
||||
|
return { |
||||
|
_: _, |
||||
|
dayjs: dayjs, |
||||
|
tableHeader: [], |
||||
|
formHeader: [], |
||||
|
tableData: [], |
||||
|
selectionData: [], |
||||
|
dialogFrom: { |
||||
|
visible: false, |
||||
|
title: "新增处方", |
||||
|
type: "add", |
||||
|
formHeader: [], |
||||
|
formData: {} |
||||
|
}, |
||||
|
sortObj: {}, |
||||
|
loading: false, |
||||
|
addDataVisible: false, |
||||
|
form: { |
||||
|
jiageDate: "", |
||||
|
jiageStr: "", |
||||
|
}, |
||||
|
fileOriData: null, |
||||
|
fileList: [] |
||||
|
} |
||||
|
}, |
||||
|
methods: { |
||||
|
/** |
||||
|
* 上传表格检查 |
||||
|
*/ |
||||
|
beforeAvatarUpload(rawFile) { |
||||
|
let imgList = ['text/csv', 'application/vnd.ms-excel', "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"] |
||||
|
if (imgList.indexOf(rawFile.type) === -1) { |
||||
|
this.$msgbox.alert('请上传excel,csv格式的表格文件!') |
||||
|
return false |
||||
|
} else if (rawFile.size / 1024 / 1024 > 50) { |
||||
|
this.$msgbox.alert('表格文件的大小为小于50MB,数据过多时会处理过慢') |
||||
|
return true |
||||
|
} |
||||
|
return true |
||||
|
}, |
||||
|
//表格增加数据 |
||||
|
async successSubmit(opts) { |
||||
|
let that = this |
||||
|
let file = opts.file |
||||
|
this.fileDealData = [] |
||||
|
let fileReader = new FileReader() |
||||
|
fileReader.onload = async function () { |
||||
|
let data = this.result |
||||
|
let workbook = XLSX.read(data, { type: 'binary' }) |
||||
|
let sheetName = workbook.SheetNames[0] |
||||
|
let sheetData = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]) |
||||
|
let list = [] |
||||
|
for (let i = 0; i < sheetData.length; i++) { |
||||
|
let item = sheetData[i]; |
||||
|
let date = "" |
||||
|
if (typeof item.日期 === "string") { |
||||
|
date = dayjs(item.日期).format("YYYY-MM-DD") |
||||
|
} else if (typeof item.日期 === "number") { |
||||
|
date = dayjs('1900-01-01').add(item.日期 - 2, "day").format("YYYY-MM-DD") |
||||
|
} |
||||
|
console.log(164, date); |
||||
|
let findItem = _.find(that.tableData, function (dataItem) { |
||||
|
return item.品名 === dataItem.pinming && item.规格 === dataItem.guige && item.材质 === dataItem.caizhi && item.产地 === dataItem.chandi && date === dataItem.date |
||||
|
}) |
||||
|
if (findItem) { |
||||
|
list.push({ |
||||
|
序号: item.序号, |
||||
|
日期: date, |
||||
|
品名: item.品名, |
||||
|
规格: item.规格, |
||||
|
材质: item.材质, |
||||
|
产地: item.产地, |
||||
|
价格: findItem.jiage, |
||||
|
}) |
||||
|
} else { |
||||
|
list.push({ |
||||
|
序号: item.序号, |
||||
|
日期: date, |
||||
|
品名: item.品名, |
||||
|
规格: item.规格, |
||||
|
材质: item.材质, |
||||
|
产地: item.产地, |
||||
|
价格: "暂无此数", |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
that.fileList = list |
||||
|
} |
||||
|
fileReader.onerror = function (error) { |
||||
|
console.error('Error reading file:', error) |
||||
|
} |
||||
|
fileReader.readAsArrayBuffer(file) |
||||
|
}, |
||||
|
downExcel() { |
||||
|
// 将that.fileList转为表格下载 |
||||
|
let data = this.fileList |
||||
|
let ws = XLSX.utils.json_to_sheet(data) |
||||
|
let wb = XLSX.utils.book_new() |
||||
|
XLSX.utils.book_append_sheet(wb, ws, "Sheet1") |
||||
|
XLSX.writeFile(wb, `${dayjs().format('YYYY-MM-DD')}价格表.xlsx`) |
||||
|
this.fileList = [] |
||||
|
}, |
||||
|
exportAllData() { |
||||
|
// 将that.fileList转为表格下载 |
||||
|
let data = [] |
||||
|
for (let index = 0; index < this.tableData.length; index++) { |
||||
|
let item = this.tableData[index]; |
||||
|
data.push({ |
||||
|
序号: `${index + 1}`, |
||||
|
日期: item.date, |
||||
|
品名: item.pinming, |
||||
|
规格: item.guige, |
||||
|
材质: item.caizhi, |
||||
|
产地: item.chandi, |
||||
|
价格: item.jiage, |
||||
|
}) |
||||
|
} |
||||
|
let ws = XLSX.utils.json_to_sheet(data) |
||||
|
let wb = XLSX.utils.book_new() |
||||
|
XLSX.utils.book_append_sheet(wb, ws, "Sheet1") |
||||
|
XLSX.writeFile(wb, `${dayjs().format('YYYY-MM-DD')}基础价格表.xlsx`) |
||||
|
}, |
||||
|
//更新数据 |
||||
|
async updateSeach() { |
||||
|
this.loading = true |
||||
|
this.tableData = _.cloneDeep(await myDatabase.jiage.toArray()) |
||||
|
this.loading = false |
||||
|
}, |
||||
|
// 排序 |
||||
|
async headerSort(headerSort) { |
||||
|
this.sortObj = headerSort |
||||
|
await this.updateSeach() |
||||
|
}, |
||||
|
//选中数据 |
||||
|
selectChange(selection) { |
||||
|
this.selectionData = _.cloneDeep(selection) |
||||
|
}, |
||||
|
//关闭模态框 |
||||
|
cancelDialog() { |
||||
|
this.dialogFrom = { |
||||
|
visible: false, |
||||
|
title: "新增", |
||||
|
type: "add", |
||||
|
formHeader: [], |
||||
|
formData: {} |
||||
|
} |
||||
|
}, |
||||
|
//确认模态框 |
||||
|
async submitDialog() { |
||||
|
let params = { ...this.dialogFrom.formData, } |
||||
|
try { |
||||
|
await myDatabase.jiage[this.dialogFrom.type]({ ...params, update_at: dayjs().format('YYYY-MM-DD HH:mm:ss') }) |
||||
|
await this.updateSeach() |
||||
|
this.cancelDialog() |
||||
|
} catch (e) { |
||||
|
ElMessage( |
||||
|
{ |
||||
|
type: "error", |
||||
|
message: "时间不允许重复,请重新设置时间" |
||||
|
} |
||||
|
) |
||||
|
} |
||||
|
}, |
||||
|
//打开新增模态框 |
||||
|
addData() { |
||||
|
this.addDataVisible = true |
||||
|
}, |
||||
|
// 取消数据 |
||||
|
cancelData() { |
||||
|
this.form.jiageStr = "" |
||||
|
this.form.jiageDate = "" |
||||
|
this.addDataVisible = false |
||||
|
}, |
||||
|
// 新增数据 |
||||
|
async submitAddData() { |
||||
|
if (this.form.jiageStr && this.form.jiageDate) { |
||||
|
let str = this.form.jiageStr.replace(/\t/g, '').replace(/\r/g, '').replace(/\n/g, '') |
||||
|
str = `<table> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th width="16%" class="market-table-cell-1" nowrap="nowrap"> |
||||
|
品名 |
||||
|
</th> |
||||
|
<th width="16%" class="market-table-cell-2" nowrap="nowrap"> |
||||
|
规格 |
||||
|
</th> |
||||
|
<th width="16%" class="market-table-cell-3" nowrap="nowrap"> |
||||
|
材质 |
||||
|
</th> |
||||
|
<th width="16%" class="market-table-cell-place"> |
||||
|
产地 |
||||
|
</th> |
||||
|
<th width="16%" class="market-table-cell-5" nowrap="nowrap"> |
||||
|
价格 |
||||
|
</th> |
||||
|
<th width="6%" class="market-table-cell-6" nowrap="nowrap"> |
||||
|
涨跌 |
||||
|
</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
${str} |
||||
|
</table>` |
||||
|
let dom = new DOMParser().parseFromString(str, 'text/html'); |
||||
|
console.log(175, dom); |
||||
|
let tableData = tabletojson.convert(str, { |
||||
|
useFirstRowForHeadings: true, |
||||
|
// 其他自定义参数 |
||||
|
}); |
||||
|
console.log(tableData); |
||||
|
let dataList = [] |
||||
|
for (let i = 0; i < tableData.length; i++) { |
||||
|
let element = tableData[i]; |
||||
|
for (let j = 1; j < element.length; j++) { |
||||
|
let item = element[j]; |
||||
|
dataList.push({ |
||||
|
date: this.form.jiageDate, |
||||
|
pinming: item.品名, |
||||
|
guige: item.规格, |
||||
|
caizhi: item.材质, |
||||
|
chandi: item.产地, |
||||
|
jiage: item.价格, |
||||
|
note: `${this.form.jiageDate}_${item.品名}_${item.规格}_${item.材质}_${item.产地}_${item.价格}`, |
||||
|
create_at: dayjs().format('YYYY-MM-DD HH:mm:ss'), |
||||
|
update_at: dayjs().format('YYYY-MM-DD HH:mm:ss'), |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
|
console.log(310, dataList); |
||||
|
// 新增数据 |
||||
|
try { |
||||
|
await myDatabase.jiage.bulkAdd(dataList) |
||||
|
} catch (e) { |
||||
|
ElMessage({ |
||||
|
type: "error", |
||||
|
message: `数据重复,${e}` |
||||
|
}) |
||||
|
} |
||||
|
this.cancelData() |
||||
|
} else { |
||||
|
ElMessage({ |
||||
|
type: "error", |
||||
|
message: "请填写完整数据后提交" |
||||
|
}) |
||||
|
} |
||||
|
}, |
||||
|
//打开编辑数据模态框 |
||||
|
edit(row) { |
||||
|
this.dialogFrom = { |
||||
|
visible: true, |
||||
|
title: `编辑${row.note}`, |
||||
|
type: "put", |
||||
|
disabled: false, |
||||
|
formHeader: this.formHeader, |
||||
|
formData: { ...row } |
||||
|
} |
||||
|
}, |
||||
|
//打开查看数据模态框 |
||||
|
info(row) { |
||||
|
this.dialogFrom = { |
||||
|
visible: true, |
||||
|
title: `查看${row.note}`, |
||||
|
type: "info", |
||||
|
disabled: true, |
||||
|
formHeader: this.formHeader, |
||||
|
formData: { ...row } |
||||
|
} |
||||
|
}, |
||||
|
//删除数据 |
||||
|
del(row) { |
||||
|
this.deleteData([row]) |
||||
|
}, |
||||
|
//批量删除数据 |
||||
|
deleteData(delList) { |
||||
|
let tooltipList = [] |
||||
|
let idList = [] |
||||
|
for (let i = 0; i < delList.length; i++) { |
||||
|
let element = delList[i]; |
||||
|
tooltipList.push(element.note) |
||||
|
idList.push(element.id) |
||||
|
} |
||||
|
ElMessageBox.confirm( |
||||
|
`是否删除(${_.join(tooltipList, ",")})?`, |
||||
|
'danger', |
||||
|
{ |
||||
|
confirmButtonText: '确认', |
||||
|
cancelButtonText: '取消', |
||||
|
type: 'danger', |
||||
|
} |
||||
|
) |
||||
|
.then(async () => { |
||||
|
this.$refs.tableComponentRef.clearSelection() |
||||
|
await myDatabase.jiage.bulkDelete(idList) |
||||
|
await this.updateSeach() |
||||
|
}) |
||||
|
.catch((err) => { |
||||
|
ElMessage({ |
||||
|
type: 'info', |
||||
|
message: '取消删除', |
||||
|
}) |
||||
|
}) |
||||
|
|
||||
|
}, |
||||
|
//删除全部数据 |
||||
|
delAll() { |
||||
|
ElMessageBox.confirm( |
||||
|
`是否删除全部数据?此操作不可逆!`, |
||||
|
'危险操作', |
||||
|
{ |
||||
|
confirmButtonText: '确认', |
||||
|
cancelButtonText: '取消', |
||||
|
type: 'danger', |
||||
|
} |
||||
|
) |
||||
|
.then(async () => { |
||||
|
this.$refs.tableComponentRef.clearSelection() |
||||
|
await myDatabase.jiage.clear() |
||||
|
await this.updateSeach() |
||||
|
}) |
||||
|
.catch(() => { |
||||
|
ElMessage({ |
||||
|
type: 'info', |
||||
|
message: '取消删除', |
||||
|
}) |
||||
|
}) |
||||
|
}, |
||||
|
}, |
||||
|
async mounted() { |
||||
|
this.tableHeader = _.filter(tableHeaderLocal, o => o.tableShow) |
||||
|
this.formHeader = _.filter(tableHeaderLocal, o => o.formShow) |
||||
|
await this.updateSeach() |
||||
|
}, |
||||
|
} |
||||
|
</script> |
||||
|
<style scoped> |
||||
|
.rightClass { |
||||
|
padding: 8px; |
||||
|
} |
||||
|
|
||||
|
.uploadClass { |
||||
|
top: 3px; |
||||
|
} |
||||
|
|
||||
|
.inputClass { |
||||
|
display: inline-block; |
||||
|
margin: 0 8px; |
||||
|
position: relative; |
||||
|
} |
||||
|
|
||||
|
.tagClass { |
||||
|
display: inline-block; |
||||
|
margin: 0 8px; |
||||
|
width: 200px; |
||||
|
position: relative; |
||||
|
} |
||||
|
</style> |
Loading…
Reference in new issue