钜星新版审处方客户端初始提交

This commit is contained in:
2021-12-09 14:51:57 +08:00
commit b432b8624f
36 changed files with 6053 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/node_modules/

View File

@ -0,0 +1,32 @@
##############################################
# dscription \u77E9\u661F\u5BA2\u6237\u7AEF\u914D\u7F6E\u6587\u4EF6(\u6CE8\u610F\u7B49\u53F7\u4E24\u8FB9\u4E0D\u80FD\u6709\u7A7A\u683C)
# @auth \u58A8\u8863
# @time 2021-10-09
##############################################
#\u5BA2\u6237\u7AEF\u66F4\u65B0\u5730\u5740
update_url=http://192.168.1.158:8889/file
#\u5BA2\u6237\u7AEF\u5730\u5740\u914D\u7F6E
pharmacy=https://test.yunclinic.cn:7443/pharmacy
doctor=https://test.yunclinic.cn:7443/doctor
pharmacist=https://test.yunclinic.cn:7443/pharmacist
#windows\u7684C:/Users/\u7528\u6237/\u76EE\u5F55\u4E0B\u7684\u5185\u5BB9(\u5982\u679C\u662Fmac\u4E0B\u7684\u6CE8\u610F\u4FEE\u6539\u8FD9\u4E24\u4E2A\u76EE\u5F55)
#\u5BA2\u6237\u7AEF\u7528\u6237\u521B\u5EFA\u5FEB\u6377\u65B9\u5F0F\u5B58\u653E\u76EE\u5F55->lnks.json(window)
lnks_url=AppData/Local/justarData
#\u5BA2\u6237\u7AEF\u7528\u6237\u7F13\u5B58\u76EE\u5F55\u4FDD\u5B58(windows)
cache_url=AppData/Local/justarData/cache
#\u65E5\u5FD7\u914D\u7F6E
#\u65E5\u5FD7\u7EA7\u522B error->warn->info->verbose->debug->silly
log_file_level=info
log_console_level=debug
#\u65E5\u5FD7\u6587\u4EF6\u540D\uFF0C\u9ED8\u8BA4\uFF1Amain.log
log_fileName=justar_client.log
#\u65E5\u5FD7\u683C\u5F0F\uFF0C\u9ED8\u8BA4\uFF1A[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}]{scope} {text}
log_date_format=[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}]{scope} {text}
#\u65E5\u5FD7\u5927\u5C0F\uFF0C\u9ED8\u8BA4\uFF1A1048576\uFF081M\uFF09\uFF0C\u8FBE\u5230\u6700\u5927\u4E0A\u9650\u540E\uFF0C\u5907\u4EFD\u6587\u4EF6\u5E76\u91CD\u547D\u540D\u4E3A\uFF1Amain.old.log\uFF0C\u6709\u4E14\u4EC5\u6709\u4E00\u4E2A\u5907\u4EFD\u6587\u4EF6
log_maxSize=1048576
#\u4FEE\u6539\u65E5\u5FD7\u6587\u4EF6\u7684\u65E5\u5FD7\u8F93\u51FA\u4F4D\u7F6E\uFF0C\u9ED8\u8BA4\u4F4D\u7F6E\u4E3A\uFF1AC:\Users\%USERPROFILE%\AppData\Roaming\Electron\logs
log_resolvePath=appData/logs/justar_client.log

111
package.json Normal file
View File

@ -0,0 +1,111 @@
{
"name": "JUSTAR",
"version": "2.1.2",
"description": "钜星科技便民问诊系统",
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "chcp 65001 && electron . doctor--default",
"pack": "electron-builder --dir",
"dist": "electron-builder"
},
"keywords": [],
"author": "墨衣",
"license": "ISC",
"build": {
"productName": "钜星科技便民问诊系统",
"appId": "justar",
"directories": {
"output": "build"
},
"extraResources":[
{
"from": "./static",
"to": "../static"
},
{
"from": "./appData",
"to": "../appData"
}
],
"files": [
"src",
"package.json",
"node_modules"
],
"dmg": {
"contents": [
{
"x": 410,
"y": 150,
"type": "link",
"path": "/Applications"
},
{
"x": 130,
"y": 150,
"type": "file"
}
]
},
"mac": {
"icon": "./static/images/justar.ico"
},
"win": {
"icon": "./static/images/justar.ico",
"target": [
{
"target": "nsis",
"arch": [
"ia32"
]
}
],
"publish": [{
"provider": "generic",
"url": "http://192.168.1.158:8889/file"
}]
},
"linux": {
"icon": "./static/images/justar.ico"
},
"nsis": {
"oneClick": false,
"perMachine": false,
"allowElevation": true,
"allowToChangeInstallationDirectory": true,
"createDesktopShortcut": false,
"runAfterFinish": true,
"installerIcon": "./static/images/justar.ico",
"uninstallerIcon": "./static/images/justar.ico",
"include":""
}
},
"dependencies": {
"bootstrap": "^5.1.3",
"bootstrap-icons": "^1.6.1",
"electron-context-menu": "^3.1.1",
"electron-log": "^4.4.1",
"electron-updater": "^4.3.9",
"fs": "^0.0.1-security",
"jquery": "^3.6.0",
"node-fetch": "2.6.1",
"popper.js": "^1.16.1",
"windows-shortcuts": "^0.1.6"
},
"devDependencies": {
"bootstrap": "^5.1.3",
"bootstrap-icons": "^1.6.1",
"electron": "^15.0.0",
"electron-builder": "^22.13.1",
"electron-context-menu": "^3.1.1",
"electron-log": "^4.4.1",
"electron-updater": "^4.3.9",
"fs": "^0.0.1-security",
"jquery": "^3.6.0",
"node-fetch": "2.6.1",
"popper.js": "^1.16.1",
"windows-shortcuts": "^0.1.6"
}
}

114
src/css/set.css Normal file
View File

@ -0,0 +1,114 @@
.floating-button {
position: absolute;
right: 50%;
bottom: 2em;
border-radius: 20%;
z-index: 2;
box-shadow: 0 10px 20px rgba(0, 0, 0, .19), 0 6px 6px rgba(0, 0, 0, .23);
border: 0em;
}
#div {
/*设置z-index属性必须设置position:relative或absolute*/
position: relative;
/*设置div位于遮罩的上方*/
z-index: 2;
}
#cover {
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
/*设置遮罩位于div的下方*/
z-index: 1;
}
#box {
/*当弹窗显示时,屏幕滚动时,弹窗始终保持位置固定在屏幕正中,不随屏幕滚动而变化位置*/
background-color: #fff;
padding-top: 3em;
padding-left: 2em;
padding-right: 2em;
border-radius: 0.5em;
position: fixed;
width: 30rem;
height: 25rem;
position: absolute;
top: 0em;
left: 0em;
right: 0em;
bottom: 0em;
margin: auto;
/*设置弹窗位于遮罩的上方*/
z-index: 3;
/*开始时隐藏弹窗*/
display: none;
}
#box1 {
/*当弹窗显示时,屏幕滚动时,弹窗始终保持位置固定在屏幕正中,不随屏幕滚动而变化位置*/
background-color: #fff;
padding-top: 1em;
padding-left: 2em;
padding-right: 2em;
border-radius: 0.5em;
position: fixed;
width: 30rem;
height: 12rem;
position: absolute;
top: 0em;
left: 0em;
right: 0em;
bottom: 0em;
margin: auto;
/*设置弹窗位于遮罩的上方*/
z-index: 4;
/*开始时隐藏弹窗*/
display: none;
}
#box2 {
/*当弹窗显示时,屏幕滚动时,弹窗始终保持位置固定在屏幕正中,不随屏幕滚动而变化位置*/
background-color: #fff;
padding-top: 1em;
padding-left: 2em;
padding-right: 2em;
border-radius: 0.5em;
position: fixed;
width: 30rem;
height: 5rem;
position: absolute;
top: 0em;
left: 0em;
right: 0em;
bottom: 0em;
margin: auto;
/*设置弹窗位于遮罩的上方*/
z-index: 5;
/*开始时隐藏弹窗*/
display: none;
}
#box3 {
/*当弹窗显示时,屏幕滚动时,弹窗始终保持位置固定在屏幕正中,不随屏幕滚动而变化位置*/
background-color: #fff;
padding-top: 1em;
padding-left: 2em;
padding-right: 2em;
border-radius: 0.5em;
position: fixed;
width: 30rem;
height: 30rem;
position: absolute;
top: 0em;
left: 0em;
right: 0em;
bottom: 0em;
margin: auto;
/*设置弹窗位于遮罩的上方*/
z-index: 6;
/*开始时隐藏弹窗*/
display: none;
}

132
src/index.js Normal file
View File

@ -0,0 +1,132 @@
/**
* 入口函数
*/
const electron = require('electron');
const app=electron.app;
const path=require('path');
let ipcMain = electron.ipcMain;
const autoUpdater =require('electron-updater').autoUpdater;
let apppath = app.getAppPath();
//判断是否是开发状态-1 是
let is_dev=apppath.lastIndexOf("JUSTAR"+path.sep+"resources");
let respath=apppath.substring(0, apppath.lastIndexOf("resources") - 1);
let update_url=null;
let main=require(apppath+path.sep+"src"+path.sep+"js"+path.sep+"main.js");
let read_config=require(apppath+path.sep+"src"+path.sep+"js"+path.sep+"setting"+path.sep+"read_config.js");
let log=require(apppath+path.sep+"src"+path.sep+"js"+path.sep+"setting"+path.sep+"set_log.js").clog;
app.whenReady().then(()=>{
//读取及加载配置的文件
if(is_dev==-1){
read_config.readConfig(apppath);
read_config.loadConfig(apppath,runMain);
}else{
read_config.readConfig(respath);
read_config.loadConfig(respath,runMain);
}
});
//运行main函数(main_dev、main)
function runMain(configs){
update_url=configs.update_url;
//区分开发和应用的区别
if(is_dev==-1){
log.info("【开发模式下运行】")
log.info("项目根目录为:"+apppath);
log.info("项目资源目录为:"+apppath);
log.info("项目配置文件内容:【");
log.info(configs);
log.info("】");
main.createMainWindow(configs,apppath,apppath,updateHandle);
}else{
log.info("【应用模式下运行】")
log.info("项目根目录为:"+apppath);
log.info("项目资源目录为:"+respath);
log.info("项目配置文件内容:【");
log.info(configs);
log.info("】");
main.createMainWindow(configs,apppath,respath,updateHandle);
}
}
/**
* 自动检测更新程序实现
* @param mainWindow
*/
function updateHandle(mainWindow) {
let message = {
error: '检查更新出错',
checking: '正在检查更新……',
updateAva: '检测到新版本,正在下载……',
updateNotAva: '现在使用的就是最新版本,不用更新',
};
if(update_url==''){
return;
}
autoUpdater.setFeedURL(update_url);
/**
* 更新出错
*/
autoUpdater.on('error', function (error) {
mainWindow.webContents.send('message', [-1,message.error]);
});
/**
* 检查可用更新
*/
autoUpdater.on('checking-for-update', function () {
mainWindow.webContents.send('message', [1,message.checking]);
});
/**
* 有可用更新,会自动进行下载
*/
autoUpdater.on('update-available', function (info) {
mainWindow.webContents.send('message', [2,message.updateAva,info]);
});
/**
* 无可用更新
*/
autoUpdater.on('update-not-available', function (info) {
mainWindow.webContents.send('message', [0,message.updateNotAva]);
});
/**
* 更新进度
*/
autoUpdater.on('download-progress', function (progressObj) {
log.info("传过来的数据百分数样式:"+progressObj.percent);
mainWindow.webContents.send('downloadProgress', progressObj)
});
/**
* 更新完成后进行程序重启操作
* event Event
* releaseNotes String - 新版本更新公告
* releaseName String - 新的版本号
* releaseDate Date - 新版本发布的日期
* updateURL String - 更新地址
* */
autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {
ipcMain.on('isQuitAndInstall', (e, arg) => {
//是否静默更新,更新完成是否立即重启程序
autoUpdater.quitAndInstall(true,arg[0]);
app.exit();
});
mainWindow.webContents.send('isQuitAndInstall')
});
ipcMain.on("checkForUpdate",()=>{
//执行自动更新检查
autoUpdater.checkForUpdates();
})
}

View File

@ -0,0 +1,61 @@
/**
* 加载医生客户端函数
*/
const path=require('path');
const log = require(".."+path.sep+"setting"+path.sep+"set_log").clog;
const electron = require('electron');
const screen = electron.screen;
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
const print_monitor=require(".."+path.sep+"setting"+path.sep+"print_monitor");
const finger_monitor=require(".."+path.sep+"setting"+path.sep+"finger_monitor");
let doc={
createDocWindow:function (apppath,respath,main,url,updateHandle){
//阻止应用多开
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
}
log.info("加载医生客户端窗口...")
let win = new BrowserWindow({
width: (screen.getPrimaryDisplay().workAreaSize.width / 4) * 3,
height: (screen.getPrimaryDisplay().workAreaSize.height / 4) * 3,
title: "钜星科技便民问诊系统 版本 2.0",
frame: true,
show: true,
icon: respath +path.sep+"static"+path.sep+"images"+path.sep+"justar.ico",
webPreferences: {
nodeIntegration: true,
//禁止远程页面调用electron框架的window.open
nativeWindowOpen: true,
//允许跨域请求
webSecurity: false,
//允许远程调用
enableRemoteModule: true,
//防止require引入失败
contextIsolation:false
}
});
main.registerDevTool(win);
win.loadURL(url);
win.setMenu(null);
main.taskbarStar(win);
main.winTop(win);
//开启指纹登录监听程序
finger_monitor.runFingerMonitor(respath);
//开启打印列表页面监听
print_monitor.openPrinterMonitor(win,apppath,respath,main);
//监听最后一个窗口被关闭时,退出程序
win.on("close", (e) => {
e.preventDefault();
main.exitSoft(respath);
});
updateHandle(win);
}
}
module.exports=doc;

166
src/js/main.js Normal file
View File

@ -0,0 +1,166 @@
/**
* 打包后运行主函数
*/
const electron = require('electron');
const app = electron.app;
const dialog = electron.dialog;
const ipcMain = electron.ipcMain;
const shell = electron.shell;
const path=require('path');
const os=require('os');
const process=require('process')
const log = require("."+path.sep+"setting"+path.sep+"set_log").clog;
const globalShortcut = electron.globalShortcut;
const contextMenu = require('electron-context-menu');
//加载三个客户端js函数,设置js函数及打印函数
const load_set = require("."+path.sep+"setting"+path.sep+"load_set");
const load_pharmacy=require("."+path.sep+"pharmacy"+path.sep+"load_pharmacy");
const load_doctor=require("."+path.sep+"doctor"+path.sep+"load_doctor");
const load_pharmacist=require("."+path.sep+"pharmacist"+path.sep+"load_pharmacist");
let main ={
webPath:null,
createMainWindow:function (configs, apppath,respath,updateHandle) {
log.info("开始加载窗口...");
this.addContextMenu(respath);
log.info("加载右键菜单成功...");
this.setCacheAndPath(respath,apppath,configs.cache_url);
log.info(this.webPath)
if(this.webPath == 'pharmacy'){
load_pharmacy.createPhamWindow(apppath,respath,this,configs.pharmacy,updateHandle);
}else if(this.webPath == 'doctor'){
load_doctor.createDocWindow(apppath,respath,this,configs.doctor,updateHandle);
}else if(this.webPath=='pharmacist'){
load_pharmacist.createPhacWindow(apppath,respath,this,configs.pharmacist,updateHandle);
}else{
load_set.createSetWindow(apppath,respath,this,configs.lnks_url,updateHandle);
}
},
//设置缓存及访问客户端(非开发模式)
setCacheAndPath:function(respath,apppath,cpath){
let params=null;
if(respath==apppath){
params = process.argv[2];
}else{
params = process.argv[1];
}
//统一路径斜杠
if(os.type()=='Windows_NT'){
cpath=cpath.replaceAll("/",path.sep);
}
log.info("快捷方式传过来的参数【"+process.argv+"】");
log.info()
if (params != null) {
this.webPath = params.substring(0, params.lastIndexOf("--"));
let cachPath = params.substring(params.lastIndexOf("--") + 2);
//设置应用程序的缓存路径
app.setPath("userData", os.homedir()+path.sep+cpath +path.sep+ cachPath);
log.info("设置缓存目录【"+os.homedir()+path.sep+cpath +path.sep+ cachPath+"】成功");
}
},
//退出软件
exitSoft: function (respath) {
dialog.showMessageBox({
type: 'info',
title: '退出程序',
defaultId: 0,
icon:respath + path.sep+"static"+ path.sep+"images"+ path.sep+"justar.ico",
message: "确定要退出程序吗?",
buttons: ['确定', '取消']
}).then((index) => {
if (index.response === 0) {
app.exit();
}
});
},
//注册开发者工具
registerDevTool: function (win) {
shortcut = globalShortcut.register("Ctrl+u", () => {
win.webContents.openDevTools();
});
},
//任务栏闪烁监听
taskbarStar:function (win){
ipcMain.on("taskbar_star", function () {
win.flashFrame(true);
});
},
//窗口置顶监听
winTop:function(win){
ipcMain.on('win_top', function () {
win.moveTop();
});
},
//添加全局菜单
addContextMenu: function (respath) {
//全局上下文菜单模板
contextMenu({
menu: () => [],
prepend: (actions, params, browserWindow, dictionarySuggestions) => [
{
label: "刷新",
icon: respath + path.sep+"static"+path.sep+"images"+path.sep+"refresh.png",
click: () => {
browserWindow.reload();
/* browserWindow.webContents.send('reloadInMain',[]);*/
}
},
{
label: '关键字搜索',
icon: respath + path.sep+"static"+ path.sep+"images"+ path.sep+"search.png",
visible: params.selectionText.trim().length > 0,
click: () => {
shell.openExternal(`https://www.baidu.com/s?wd=${encodeURIComponent(params.selectionText)}`)
}
},
{
label: '剪切(CTRL+X)',
icon: respath + path.sep+"static"+ path.sep+"images"+ path.sep+"cut.png",
visible: params.selectionText.length > 0,
click: () => {
browserWindow.webContents.cut();
}
},
{
label: '复制(CTRL+C)',
icon: respath + path.sep+"static"+ path.sep+"images"+ path.sep+"copy.png",
visible: params.selectionText.trim().length > 0,
click: () => {
browserWindow.webContents.copy();
}
},
{
label: '粘贴(CTRL+V)',
icon: respath + path.sep+ "static"+ path.sep+"images"+ path.sep+"paste.png",
click: () => {
browserWindow.webContents.paste();
}
}, {
label: '全选(CTRL+A)',
icon: respath + path.sep+ "static"+ path.sep+"images"+ path.sep+"select_all.png",
click: () => {
browserWindow.webContents.selectAll();
}
},
{
label:'清除缓存',
icon:respath+ path.sep+"static"+ path.sep+"images"+ path.sep+"clear.png",
click:()=>{
browserWindow.webContents.session.clearStorageData();
browserWindow.reload();
/*browserWindow.webContents.send('reloadInMain',[]);*/
}
},
{
label: '退出程序',
icon: respath + path.sep+ "static"+ path.sep+"images"+ path.sep+"exit.png",
click: () => {
this.exitSoft(respath);
}
}]
});
}
}
module.exports=main

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 artiebits
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,141 @@
# Node.js PDF printing
[![Build Status](https://api.cirrus-ci.com/github/artiebits/pdf-to-printer.svg)](https://cirrus-ci.com/github/artiebits/pdf-to-printer)
[![codecov](https://codecov.io/gh/artiebits/pdf-to-printer/branch/master/graph/badge.svg)](https://codecov.io/gh/artiebits/pdf-to-printer)
![npm](https://img.shields.io/npm/dw/pdf-to-printer)
A utility to print PDF files from Node.js and Electron.
* ✅ Works on Windows and Unix-like operating systems.
* ✅ Supports label printers such as [Rollo](https://www.rolloprinter.com/) and [Zebra](https://www.zebra.com/us/en/products/printers.html).
## Installation
Install using [`yarn`](https://yarnpkg.com/):
```bash
yarn add pdf-to-printer
```
Or [`npm`](https://www.npmjs.com/):
```bash
npm install --save pdf-to-printer
```
## Basic Usage
Print a PDF file to the default printer:
```javascript
import ptp from "pdf-to-printer";
ptp
.print("assets/pdf-sample.pdf")
.then(console.log)
.catch(console.error);
```
## API
### `.print(pdf[, options]) => Promise<void>`
**Arguments**
1. `pdf` (`string`): PDF file to print. Will throw an error if no PDF specified. **Note**: It must be a path to a PDF existing in the file system.
You may take a look at [this example](/examples/express-server) if you need to download your PDF file first.
2. `options` (`Object` [optional]):
- `options.printer`: (`string` [optional]): Print to the specified printer. Will print to the default printer if name not specified. If the printer name mistyped or specified printer does not exist, nothing will print.
- `options.unix`: (`array` [optional]): Since we use **lp** to print documents on Unix-like operating systems you can pass any available in [this list option](https://www.computerhope.com/unix/ulp.htm).
- `options.win32`: (`array` [optional]): And since we use **SumatraPDF** to print documents on Windows you can pass any available in [this list option](https://www.sumatrapdfreader.org/docs/Command-line-arguments.html).
**Returns**
`Promise<void>`.
**Examples**
To print a PDF file to the default printer:
```javascript
ptp
.print("assets/pdf-sample.pdf")
.then(console.log)
.catch(console.error);
```
To print to a specific printer, add the name of the printer to options:
```javascript
const options = {
printer: "Zebra"
};
ptp
.print("assets/pdf-sample.pdf", options)
.then(console.log)
.catch(console.error);
```
To scale the PDF to fit into the printable area of the paper on both Windows and Unix operating systems:
```javascript
const options = {
printer: "Zebra",
unix: ["-o fit-to-page"],
win32: ['-print-settings "fit"']
};
ptp
.print("assets/pdf-sample.pdf", options)
.then(console.log)
.catch(console.error);
```
### `.getPrinters() => Promise<string[]>`
**Returns**
`Promise<string[]>`: List of available printers.
**Examples**
```javascript
ptp
.getPrinters()
.then(console.log)
.catch(console.error);
```
### `.getDefaultPrinter() => Promise<string>`
**Returns**
`Promise<string>`: Default printer.
**Examples**
```javascript
ptp
.getDefaultPrinter()
.then(console.log)
.catch(console.error);
```
## More examples
We have a few examples in the [source code](/examples).
## Contact
Please do not hesitate to report a bug or suggest an idea. You can do it [here](https://github.com/artiebits/pdf-to-printer/issues/new/choose).
## Sponsor this project
If you rely on this package please consider supporting it https://www.buymeacoffee.com/artiebits. I would appreciate it.
## License
[MIT](LICENSE)

View File

@ -0,0 +1,76 @@
# For documentation, see https://www.sumatrapdfreader.org/settings/settings3.2.html
MainWindowBackground = #80fff200
EscToExit = false
ReuseInstance = false
UseSysColors = false
RestoreSession = true
TabWidth = 300
FixedPageUI [
TextColor = #000000
BackgroundColor = #ffffff
SelectionColor = #f5fc0c
WindowMargin = 2 4 2 4
PageSpacing = 4 4
]
EbookUI [
FontName = Georgia
FontSize = 12.5
TextColor = #5f4b32
BackgroundColor = #fbf0d9
UseFixedPageUI = false
]
ComicBookUI [
WindowMargin = 0 0 0 0
PageSpacing = 4 4
CbxMangaMode = false
]
ChmUI [
UseFixedPageUI = false
]
ExternalViewers [
]
ShowMenubar = true
ReloadModifiedDocuments = true
FullPathInTitle = false
ZoomLevels = 8.33 12.5 18 25 33.33 50 66.67 75 100 125 150 200 300 400 600 800 1000 1200 1600 2000 2400 3200 4800 6400
ZoomIncrement = 0
PrinterDefaults [
PrintScale = shrink
]
ForwardSearch [
HighlightOffset = 0
HighlightWidth = 15
HighlightColor = #6581ff
HighlightPermanent = false
]
CustomScreenDPI = 0
RememberStatePerDocument = true
UiLanguage = cn
ShowToolbar = true
ShowFavorites = false
AssociateSilently = false
CheckForUpdates = true
RememberOpenedFiles = true
EnableTeXEnhancements = false
DefaultDisplayMode = automatic
DefaultZoom = fit page
WindowState = 1
WindowPos = 0 0 0 0
ShowToc = true
SidebarDx = 0
TocDy = 0
ShowStartPage = true
UseTabs = true
FileStates [
]
SessionData [
]
TimeOfLastUpdateCheck = 0 0
OpenCountWeek = 523
# Settings after this line have not been recognized by the current version

Binary file not shown.

View File

@ -0,0 +1 @@
!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var r=e();for(var n in r)("object"==typeof exports?exports:t)[n]=r[n]}}(global,(function(){return function(t){var e={};function r(n){if(e[n])return e[n].exports;var i=e[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)r.d(n,i,function(e){return t[e]}.bind(null,i));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=2)}([function(t,e,r){"use strict";const{execFile:n}=r(5);t.exports=(t,e=[],r)=>new Promise((i,o)=>{n(t,e,(t,e)=>{t?o(t):i(r?r(e):e)})})},function(t,e){t.exports=require("fs")},function(t,e,r){"use strict";switch(r(3).platform()){case"darwin":case"linux":t.exports={print:r(4),getPrinters:r(6),getDefaultPrinter:r(7)};break;case"win32":t.exports={print:r(8),getPrinters:r(11),getDefaultPrinter:r(12)};break;default:!function(){throw new Error("Platform not supported")}()}},function(t,e){t.exports=require("os")},function(t,e,r){"use strict";const n=r(1),i=r(0);t.exports=(t,e={})=>{if(!t)throw"No PDF specified";if("string"!=typeof t)throw"Invalid PDF name";if(!n.existsSync(t))throw"No such file";const r=[t],{printer:o,unix:s}=e;if(o&&r.push("-d",o),s){if(!Array.isArray(s))throw"options.unix should be an array";s.map(t=>r.push(...t.split(" ")))}return i("lp",r)}},function(t,e){t.exports=require("child_process")},function(t,e,r){"use strict";const n=r(0);t.exports=()=>n("lpstat",["-a"],t=>t.trim().split("\n").map(t=>t.substr(0,t.indexOf(" "))))},function(t,e,r){"use strict";const n=r(0);t.exports=()=>n("lpstat",["-d"],t=>t.substr(t.indexOf(":")+1).trim())},function(t,e,r){"use strict";const n=r(9),i=r(1),o=r(0),{fixPathForAsarUnpack:s}=r(10);t.exports=(t,e={})=>{if(!t)throw"No PDF specified";if("string"!=typeof t)throw"Invalid PDF name";if(!i.existsSync(t))throw"No such file";let r=n.join(__dirname,"SumatraPDF.exe");r=s(r);const u=[],{printer:c,win32:p}=e;if(p){if(!Array.isArray(p))throw"options.win32 should be an array";p.map(t=>u.push(...t.split(" ")))}else c?u.push("-print-to",c):u.push("-print-to-default"),u.push("-silent");return u.push(t),o(r,u)}},function(t,e){t.exports=require("path")},function(t,e,r){"use strict";r.r(e),r.d(e,"fixPathForAsarUnpack",(function(){return n}));"electron"in process.versions&&process.mainModule&&process.mainModule.filename.includes("app.asar");const n=t=>t.replace("/app.asar","")},function(t,e,r){"use strict";const n=r(0);t.exports=()=>n("wmic",["printer","get","name"],t=>t.trim().split(/\s*[\r\n]+/).slice(1))},function(t,e,r){"use strict";const n=r(0);t.exports=()=>n("wmic",["printer","get","name,default"],t=>{const e=t.trim().split(/\s*[\r\n]+/).slice(1).filter(t=>0===t.indexOf("TRUE"));return 0===e.length?"":e[0].replace(/TRUE\s+/,"")})}])}));

View File

@ -0,0 +1,11 @@
export interface Options {
printer?: string;
unix?: string[];
win32?: string[];
}
export function print(path: string, options?: any): Promise<void>;
export function getPrinters(): Promise<string[]>;
export function getDefaultPrinter(): Promise<string>;

View File

@ -0,0 +1,91 @@
{
"_from": "pdf-to-printer",
"_id": "pdf-to-printer@1.5.4",
"_inBundle": false,
"_integrity": "sha1-2YrBBEHpPmO05gYGn1e1QrRq5lI=",
"_location": "/pdf-to-printer",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "pdf-to-printer",
"name": "pdf-to-printer",
"escapedName": "pdf-to-printer",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npm.taobao.org/pdf-to-printer/download/pdf-to-printer-1.5.4.tgz",
"_shasum": "d98ac10441e93e63b4e606069f57b542b46ae652",
"_spec": "pdf-to-printer",
"_where": "E:\\Work\\rmus\\rmus_client",
"author": {
"name": "artiebits",
"email": "artur.khusaenov@gmail.com"
},
"bugs": {
"url": "https://github.com/artiebits/pdf-to-printer/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "A utility to print PDF files from Node.js and Electron",
"devDependencies": {
"@babel/cli": "7.12.1",
"@babel/core": "7.12.3",
"@babel/preset-env": "7.10.4",
"babel-jest": "26.5.2",
"clean-webpack-plugin": "3.0.0",
"copy-webpack-plugin": "5.1.1",
"husky": "^4.3.0",
"jest": "26.5.3",
"lint-staged": "^10.4.2",
"prettier": "2.1.2",
"webpack": "4.43.0",
"webpack-cli": "3.3.12"
},
"files": [
"dist"
],
"homepage": "https://github.com/artiebits/pdf-to-printer#readme",
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"keywords": [
"pdf",
"printer",
"pdf-printer",
"zebra-printer",
"rollo-printer",
"node.js",
"electron",
"windows",
"macos",
"linux"
],
"license": "MIT",
"lint-staged": {
"src/**/*.{js,ts,json,md}": [
"prettier --write"
]
},
"main": "dist/bundle.js",
"name": "pdf-to-printer",
"repository": {
"type": "git",
"url": "git+https://github.com/artiebits/pdf-to-printer.git"
},
"scripts": {
"build": "webpack --config webpack.production.config.js",
"lint": "prettier --write 'src/**/*.{js,ts,json,md}' 'webpack.production.config.js' 'examples'",
"prepublishOnly": "npm run lint && npm run test && npm run build",
"test": "jest"
},
"types": "dist/types.d.ts",
"version": "1.5.4"
}

View File

@ -0,0 +1,61 @@
/**
* 加载药师函数
*/
const path=require('path');
const log = require(".."+path.sep+"setting"+path.sep+"set_log").clog;
const electron = require('electron');
const screen = electron.screen;
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
const print_monitor=require(".."+path.sep+"setting"+path.sep+"print_monitor");
const finger_monitor=require(".."+path.sep+"setting"+path.sep+"finger_monitor");
let pharmacist={
createPhacWindow:function (apppath,respath,main,url,updateHandle){
//阻止应用多开
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
}
log.info("加载药师客户端窗口...")
let win = new BrowserWindow({
width: (screen.getPrimaryDisplay().workAreaSize.width / 4) * 3,
height: (screen.getPrimaryDisplay().workAreaSize.height / 4) * 3,
title: "钜星科技便民问诊系统 版本 2.0",
frame: true,
show: true,
icon: respath +path.sep+"static"+path.sep+"images"+path.sep+"justar.ico",
webPreferences: {
nodeIntegration: true,
//禁止远程页面调用electron框架的window.open
nativeWindowOpen: true,
//允许跨域请求
webSecurity: false,
//允许远程调用
enableRemoteModule: true,
//防止require引入失败
contextIsolation:false
}
});
main.registerDevTool(win);
win.loadURL(url);
win.setMenu(null);
main.taskbarStar(win);
main.winTop(win);
//开启指纹登录监听程序
finger_monitor.runFingerMonitor(respath);
//开启打印列表页面监听
print_monitor.openPrinterMonitor(win,apppath,respath,main);
//监听最后一个窗口被关闭时,退出程序
win.on("close", (e) => {
e.preventDefault();
main.exitSoft(respath);
});
updateHandle(win);
}
}
module.exports=pharmacist;

View File

@ -0,0 +1,82 @@
/**
* 加载门店页面函数
*/
const path=require('path');
const log = require(".."+path.sep+"setting"+path.sep+"set_log").clog;
const electron = require('electron');
const screen = electron.screen;
const app = electron.app;
const ipcMain=electron.ipcMain;
const BrowserWindow = electron.BrowserWindow;
const process = require('child_process');
const print_monitor=require(".."+path.sep+"setting"+path.sep+"print_monitor");
const finger_monitor=require(".."+path.sep+"setting"+path.sep+"finger_monitor");
let pharmacy={
createPhamWindow:function (apppath,respath,main,url,updateHandle){
//阻止应用多开
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
}
log.info("加载门店客户端窗口...");
let win = new BrowserWindow({
//直接设置最大宽高
width: (screen.getPrimaryDisplay().workAreaSize.width/4)*3,
height: (screen.getPrimaryDisplay().workAreaSize.height/4)*3,
title: "钜星科技便民问诊系统 版本 2.0",
frame: false,
show: false,
icon: respath +path.sep+"static"+path.sep+"images"+path.sep+"justar.ico",
webPreferences: {
nodeIntegration: true,
//允许跨域请求
webSecurity: false,
//允许远程调用
enableRemoteModule: true,
//防止require引入失败
contextIsolation:false,
//禁止远程页面调用electron框架的window.open
nativeWindowOpen: true
}
});
//窗口最大化
win.maximize();
//使窗口获得焦点
win.show()
main.registerDevTool(win);
win.loadURL(url);
win.setMenu(null);
main.taskbarStar(win);
main.winTop(win);
//开启指纹登录监听程序
finger_monitor.runFingerMonitor(respath);
//开启打印列表页面监听
print_monitor.openPrinterMonitor(win,apppath,respath,main);
//
ipcMain.on("getSerialNumber",function (event, args){
process.exec('wmic bios get serialnumber',function (error, stdout, stderr) {
if (error !== null) {
log.error("获取本机SN码失败,异常如下:"+error);
}else{
let serial=stdout.replaceAll("SerialNumber","");
serial=serial.replace(/[\r\n]/g,"");
serial=serial.replace(/\ +/g,"");
event.returnValue=serial;
/*win.webContents.executeJavaScript("let pharmacy_sn='"+serial+"';");*/
}
});
});
//监听最后一个窗口被关闭时,退出程序
win.on("close", (e) => {
e.preventDefault();
main.exitSoft(respath);
});
updateHandle(win);
}
}
module.exports=pharmacy;

View File

@ -0,0 +1,44 @@
/**
* 指纹监听函数
*/
const dpath=require('path');
const log = require("."+dpath.sep+"set_log").clog;
const spawn = require('child_process').spawn
const process=require('process')
let finger_monitor={
//需要启动服务名称
cmdStr:'CrtechFingerprintWeb.exe',
cmdPath:'',
workerProcess:null,
runFingerMonitor:function (path){
this.cmdPath = path + dpath.sep+"static"+dpath.sep+"software";
log.info("指纹程序存放目录为:【"+this.cmdPath+"】");
// 执行命令行如果命令不需要路径或就是项目根目录则不需要cwd参数
this.workerProcess = spawn(this.cmdStr, { cwd: this.cmdPath, maxBuffer: 10240 * 1024 });
/* this.exit();
this.originPrintOut();
this.errorPrintOut();
this.beforeCloseOut();*/
},
//退出指纹程序监听
exit:function(){
process.on('exit',function(){
this.workerProcess.kill();
});
},
//正常输出监听
originPrintOut:function(){
this.workerProcess.stdout.on('data', function (data) {});
},
//错误输出监听
errorPrintOut:function(){
this.workerProcess.stderr.on('data', function (data) {});
},
//关闭之前输出监听
beforeCloseOut:function (){
this.workerProcess.on('close', function (code) {});
}
}
module.exports=finger_monitor

View File

@ -0,0 +1,51 @@
/**
* 加载配置页面函数
*/
const path=require('path');
const os=require('os');
const log = require("."+path.sep+"set_log").clog;
const electron = require('electron');
const app = electron.app;
const screen = electron.screen;
const BrowserWindow = electron.BrowserWindow;
let setting ={
createSetWindow:function(apppath,respath,main,lnks_url,updateHandle){
//阻止应用多开
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
}
log.info("加载设置窗口...");
let win = new BrowserWindow({
width: (screen.getPrimaryDisplay().workAreaSize.width/4)*3,
height: (screen.getPrimaryDisplay().workAreaSize.height/4)*3,
title: "钜星科技便民问诊系统 版本 2.0",
icon: respath +path.sep+"static"+path.sep+"images"+path.sep+"justar.ico",
webPreferences: {
//是否启用node继承
nodeIntegration: true,
//禁止加载页面调用到electron得window.open
nativeWindowOpen: true,
//防止require引入失败
contextIsolation:false,
}
});
win.setMenu(null);
main.registerDevTool(win);
win.loadFile(apppath+path.sep+"src"+path.sep+"views"+path.sep+"setting.html");
win.webContents.on('did-frame-finish-load',function (){
//传递配置的configs参数
if(os.type()=='Windows_NT'){
lnks_url=lnks_url.replaceAll("/",path.sep);
}
win.webContents.send('toConfig',[respath,os.homedir()+path.sep+lnks_url]);
});
//监听最后一个窗口被关闭时,退出程序
win.on("close", (e) => {
e.preventDefault();
main.exitSoft(respath);
});
updateHandle(win);
}
}
module.exports=setting;

View File

@ -0,0 +1,100 @@
/**
* 打印监听函数
*/
const path=require('path');
const log = require("."+path.sep+"set_log").clog;
const electron = require('electron');
const screen = electron.screen;
const BrowserWindow = electron.BrowserWindow;
const ipcMain = electron.ipcMain;
const print_operation=require("."+path.sep+"print_operation");
let print_monitor={
printerList_win:null,
//创建打印列表窗口
createPrinWindow:function(parent_win,apppath,respath,main,pdf_url){
printerList_win = new BrowserWindow({
width: (screen.getPrimaryDisplay().workAreaSize.height / 5) * 2,
height: (screen.getPrimaryDisplay().workAreaSize.height / 5) * 3,
fullscreenable: false,
resizable: false,
show: false,
parent: parent_win,
modal: true,
title: "选择打印机",
icon: respath +path.sep+"static"+path.sep+"images"+path.sep+"justar.ico",
webPreferences: {
nodeIntegration: true,
nativeWindowOpen: true,
//防止require引入失败
contextIsolation:false
}
});
//加载打印机列表数据监听
this.loadPrinterList(printerList_win,pdf_url);
printerList_win.setMenu(null);
printerList_win.loadFile(apppath+path.sep+"src"+path.sep+"views"+path.sep+"list_printer.html");
main.registerDevTool(printerList_win);
//开启打印监听
this.openPrinting(printerList_win);
//开启关闭打印列表页面监听
this.closePrintlistListener(printerList_win);
//当前打印列表窗口被关闭前监听
this.closePrintlistWindowListener(printerList_win);
},
//开启打印列表页面监听
openPrinterMonitor:function(parent_win,apppath,respath,main){
$this=this;
//审处方调用
ipcMain.on('list_printer', function (event, pdf_url) {
$this.createPrinWindow(parent_win,apppath,respath,main,pdf_url)
});
},
//加载打印页面的打印机列表数据监听
loadPrinterList:function(win,pdf_url){
win.once('ready-to-show', () => {
// 加载完成后, 发送打印机列表数据到list_printer.html
print_operation.getPrinterList().then(listPrinter => {
return listPrinter
}).then(listPrinter => {
print_operation.getDefaultPrinter().then(defaultPrinter => {
let data = {
listPrinter: listPrinter,
defaultPrinter: defaultPrinter,
pdf_url: pdf_url
}
win.show();
let json_data = JSON.stringify(data)
log.info("打印机列表数据【"+json_data+"】")
win.webContents.send('printerData', json_data);
});
});
})
},
//开启打印监听
openPrinting:function(win){
ipcMain.on('print', function (event, json_data) {
let data = JSON.parse(json_data)
log.info("打印开始,打印地址为:【"+json_data+"】")
print_operation.printing(data.pdf_url, data.printer,win);
});
},
closePrintlistListener:function (win){
ipcMain.once('close_listPrinter', function (e) {
win.close();
});
},
//关闭打印列表窗口监听
closePrintlistWindowListener:function(win) {
win.on("close", (e) => {
ipcMain.removeAllListeners('close_listPrinter');
});
}
}
module.exports = print_monitor;

View File

@ -0,0 +1,60 @@
/**
* 打印操作相关函数
*/
const os = require('os');
const fs = require("fs");
const path = require("path");
const fetch = require("node-fetch");
const pdf_printer = require(".."+path.sep+"module"+path.sep+"pdf-to-printer");
const log = require("."+path.sep+"set_log").clog;
let printOperation={
//获取打印机列表
getPrinterList:function(){
return pdf_printer.getPrinters();
},
//获取默认打印机
getDefaultPrinter:function(){
return pdf_printer.getDefaultPrinter();
},
//打印...
printing:function (pdfUrl, printer_name,win){
fetch(pdfUrl)
.then(res => res.buffer())
.then(buffer => {
const pdfPath = this.saveTemporaryFolder(buffer);
log.info("pdf下载完毕, 准备开始打印, 路径:【"+pdfPath+"】")
pdf_printer
.print(pdfPath, printer_name)
.then(this.onSuccess(win))
.catch(this.onError())
.finally(() => this.removePdf(pdfPath));
});
},
//保存pdf到临时文件夹
saveTemporaryFolder:function(buffer){
const pdfPath = path.join(os.tmpdir(), this.getRandomName() + ".pdf");
fs.writeFileSync(pdfPath, buffer, "binary");
return pdfPath;
},
//删除内暂存的pdf
removePdf:function(pdfPath){
fs.unlinkSync(pdfPath);
},
//生成随机pdf名称
getRandomName:function(){
return Math.random().toString(36).substring(2);
},
//成功回调
onSuccess:function (win){
win.close();
log.info("print success!");
},
//失败回调
onError:function(){
log.error(error)
}
}
module.exports = printOperation;

View File

@ -0,0 +1,40 @@
/**
* 读取default_config.properties配置文件模块
*/
const fs = require("fs");
const readline = require("readline")
const dpath=require('path')
let set_log=require("."+dpath.sep+"set_log.js");
let readlineObj=null;
let read_config={
configs:{},
readObj:readlineObj,
readConfig:function (path){
let fRead = fs.createReadStream(path + dpath.sep+"appData"+dpath.sep+"config"+dpath.sep+"config.properties");
readlineObj= readline.createInterface({
input: fRead
});
readlineObj.on('line', (line) => {
let tmp = line.toString(),
index = tmp.indexOf('#');
if (index != 0) {
let strIdx = tmp.indexOf('='),
key = tmp.substr(0, strIdx),
value = tmp.substr(strIdx + 1);
if (key.length > 0) {
this.configs[key] = value;
}
}
});
},
loadConfig:function (path,callback){
readlineObj.on('close', () => {
set_log.setlog(this.configs,path);
set_log.clog.info("开始启动程序...");
set_log.clog.info("读取配置文件完成...");
callback(this.configs);
});
}
}
module.exports=read_config;

20
src/js/setting/set_log.js Normal file
View File

@ -0,0 +1,20 @@
/**
* 配置日志函数
*/
const log = require('electron-log');
const dpath=require('path')
let config_log={
setlog:function (configs,path){
log.transports.file.level = configs.log_file_level;
log.transports.console.level = configs.log_console_level;
log.transports.file.fileName = configs.log_fileName;
log.transports.file.format = configs.log_date_format;
log.transports.file.maxSize = configs.log_maxSize;
let logUrl=configs.log_resolvePath;
logUrl=logUrl.replaceAll("/",dpath.sep);
log.transports.file.resolvePath = () => path +dpath.sep+ logUrl;
},
clog:log
}
module.exports=config_log;

136
src/views/list_printer.html Normal file
View File

@ -0,0 +1,136 @@
<!DOCTYPE html>
<html>
<head>
<title>选择打印机</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link href="../../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
<link href="../../node_modules/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet" />
</head>
<style>
html, body {
height: 100%;
}
.container-fluid {
height: 100%;
padding: 5% 0;
}
.list-group {
height: 80%;
overflow: auto;
margin-bottom: 10%;
}
.printer-btn-box {
display: flex;
justify-content: flex-end;
padding: 0 3%;
}
.printer-btn {
width: 100%;
display: flex;
justify-content: flex-end;
}
.active {
background-color: #c6c9ce !important;
border-color: #c6c9ce !important;
}
.printer-button {
width: 65px;
margin-right: 10px;
background-color: #4495ec !important;
border-color: #4495ec !important;
}
.printer-button:hover {
background-color: #4495ec !important;
border-color: #4495ec !important;
}
.cancel-button {
width: 65px;
color: #4495ec !important;
background-color: #fff !important;
border-color: #4495ec !important;
}
.cancel-button:hover {
color: #4495ec !important;
background-color: #fff !important;
border-color: #4495ec !important;
}
</style>
<body>
<div class="container-fluid" id="div">
<div class="list-group">
</div>
<div class="printer-btn-box">
<div class="printer-btn">
<button type="button" class="btn btn-success printer-button">打印</button>
<button type="button" class="btn btn-danger cancel-button">取消</button>
</div>
</div>
</div>
</body>
<script type="text/javascript">
window.$ = window.jQuery = require('jquery');
const ipcRenderer = require('electron').ipcRenderer;
let printData = {
printer: '',
pdf_url: ''
}
$(function () {
// 获取打印机数据,拼接打印机列表
ipcRenderer.on('printerData', function (event, json_data) {
let data = JSON.parse(json_data)
let defaultPrinter = data.defaultPrinter;
printData.pdf_url = data.pdf_url;
// 绘制页面
let html = [];
for (const printer of data.listPrinter) {
if (printer === defaultPrinter) {
html.push(`<a href="#" class="list-group-item list-group-item-action active" data-name="${printer}">
<i class="bi bi-printer-fill"></i> &nbsp;${printer}
</a>
`)
continue;
}
html.push(`<a href="#" class="list-group-item list-group-item-action" data-name="${printer}">
<i class="bi bi-printer-fill"></i> &nbsp;${printer}
</a>
`)
}
$(".list-group").html(html.join(''));
})
// 绑定列表点击事件
$(".list-group").on('click', 'a', function () {
$(".list-group a").removeClass('active');
$(this).addClass('active');
printData.printer = $(this).data('name');
})
// 绑定打印点击事件
$(".printer-button").click(function () {
let data = JSON.stringify(printData);
ipcRenderer.send('print', data)
});
// 绑定取消打印事件
$(".cancel-button").click(function () {
ipcRenderer.send('close_listPrinter');
})
})
</script>

411
src/views/setting.html Normal file
View File

@ -0,0 +1,411 @@
<!DOCTYPE html>
<html>
<head>
<title>钜星应用程序管理工具</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link href="../../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="../../node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<link href="../css/set.css" rel="stylesheet">
</head>
<body>
<div class="container-fluid" id="div">
<table class="table table-striped " style="text-align: center">
<tr>
<th>编号</th>
<th>端口</th>
<th>快捷地址</th>
<th>缓存文件夹</th>
<th colspan="2">操作</th>
</tr>
</table>
</div>
<div id="cover"></div>
<div id="box">
<select id="weburl" class="form-control" onchange="clientChange()">
</select><br/>
<label style="color: red;">注意:以下项不允许与其它快捷方式一致!!</label>
<input id="lnkName" placeholder="快捷名称(必填,不能与其它快捷方式名称一致)" class="form-control"/>
<br/>
<input id="cachePath" placeholder="缓存名称(必填,不能与其它缓存位置一致)" class="form-control"/>
<br/>
<div style="margin-left: 20%;padding-top: 2em">
<input type="button" onclick="createInk()" class="btn btn-success" value="生成"/>
<input type="button" onclick="exit()" class="btn btn-danger" value="退出" style="margin-left: 30%;"/>
</div>
</div>
<!--确认提示框-->
<div id="box1">
<div class="panel panel-default">
<div class="panel-heading">
<h5>删除提示</h5>
<hr/>
</div>
<div class="panel-body">
<span>是否删除此条桌面快捷方式?</span>
<div style="margin-left: 20%;padding-top: 2em">
<input type="button" onclick="deleteConfirm()" class="btn btn-success" value="确认"/>
<input type="button" onclick="exit1()" class="btn btn-danger" value="取消" style="margin-left: 30%;"/>
</div>
</div>
</div>
</div>
<!--更新进度展示框-->
<div id="box2">
<!-- 更新信息提示-->
<div id="update_label"></div>
<!--更新进度条-->
<div class="progress">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="60"
aria-valuemin="0" aria-valuemax="100" style="width: 0%;">
<span class="sr-only"></span>
</div>
</div>
</div>
<!--确认更新提示框-->
<div id="box3">
<div class="panel panel-default">
<div class="panel-heading" id="update_confirm_header" style="margin-left: 29%"></div>
<hr/>
<div class="panel-body" style="width: 100%;height: 25rem">
<ul class="list-group" id="update_confirm_content" style="text-align: center"></ul>
<div style="padding-left: 20%;height: 5rem">
<div class="checkbox">
<label style="font-size: 12px">
<input type="checkbox" class="is_restart" value="1">
更新后是否重新启动程序?
</label>
</div>
<div>
<input type="button" onclick="updateConfirm()" class="btn btn-success" value="立即升级"/>
<input type="button" onclick="exit2()" class="btn btn-danger" value="取消" style="margin-left: 30%;"/>
</div>
</div>
</div>
</div>
</div>
<input type="button" id="create" class="btn btn-success floating-button" value="创建">
<script type="text/javascript">
const dpth=require('path');
const log = require(".."+dpth.sep+"js"+dpth.sep+"setting"+dpth.sep+"set_log").clog;
const fs = require("fs");
const ws = require('windows-shortcuts');
const os=require('os');
let desktop = dpth.join(os.homedir(), 'Desktop');
let ele = require('electron');
let ipcRenderer = ele.ipcRenderer;
window.$ = window.jquery = require('jquery');
let update_info = {};
log.info("-->进入配置页面...");
//进行程序检查更新
ipcRenderer.send("checkForUpdate");
//程序更新信息监听
ipcRenderer.on("message", (event, args) => {
if (args[0] == -1) {
$("#update_label").html("<span style='color:red'>" + args[1] + "</span>");
setTimeout(function () {
$("#box2").hide();
if (!$("#box1").is(":visible") && !$("#box").is(":visible") && !$("#box3").is(":visible")) {
$("#cover").css("cssText", "background:");
$("#create").removeAttr("disabled");
$(".delete").removeAttr("disabled");
}
}, 1500)
} else if (args[0] == 2) {
log.info(args[1]);
$("#update_label").html(args[1]);
update_info = args[2];
//检查到可用更新弹出下载进度弹框
$("#box2").show();
$("#cover").css("cssText", "background:#aaa");
//禁用创建和删除按钮
$("#create").attr("disabled", "disabled");
$(".delete").attr("disabled", "disabled");
} else {
log.info(args[1]);
}
});
//下载进度条实时更新
ipcRenderer.on("downloadProgress", (event, progressObj) => {
let downloadPercent = progressObj.percent || 0;
log.info("传过来的数据百分数样式:" + progressObj.percent);
$(".progress-bar").css("cssText", "width:" + downloadPercent + "%");
$(".sr-only").html(downloadPercent + "%");
});
//下载完成立即进行重启安装
ipcRenderer.on("isQuitAndInstall", () => {
$("#box2").hide();
$("#update_confirm_header").html("<h5>" + update_info.version + "版本说明</h5>");
$("#update_confirm_content").html(update_info.updateInfo);
$("#box3").show();
});
//更新确认提示框
function updateConfirm() {
let is_restart = $(".is_restart").val();
$("#box3").hide();
$("#cover").css("cssText", "background:");
$("#create").removeAttr("disabled");
$(".delete").removeAttr("disabled");
if (is_restart == "1") {
ipcRenderer.send("isQuitAndInstall", [true]);
} else {
ipcRenderer.send("isQuitAndInstall", [false]);
}
}
function exit2() {
$("#box3").hide();
$("#cover").css("cssText", "background:");
$("#create").removeAttr("disabled");
$(".delete").removeAttr("disabled");
}
let respath = null;
let lnkList = {};
let lnks_url=null;
//接收传过来得配置信息
ipcRenderer.on('toConfig', function (event, data) {
respath = data[0];
loadPortSet();
lnks_url=data[1];
loadInit(respath,data[1]);
});
let j = null;
let lnk_url = null;
//删除快捷方式
function deleteLnk(index, url) {
$("#box1").show();
$("#cover").css("cssText", "background:#aaa");
//禁用创建和删除按钮
$("#create").attr("disabled", "disabled");
$(".delete").attr("disabled", "disabled");
j = index;
lnk_url = url;
return;
}
function deleteConfirm() {
let lnks = {};
$.each(lnkList, function (i, item) {
if (i != j) {
lnks[i] = item;
}
});
lnkList=lnks;
//删除存在的快捷方式
if (fs.existsSync(desktop+dpth.sep+lnk_url)) {
fs.unlinkSync(desktop+dpth.sep+lnk_url);
}
let jsonstr = JSON.stringify(lnks);
fs.writeFileSync(lnks_url+dpth.sep+"lnks.json", jsonstr, function (err) {
log.error("更新应用程序失败!");
});
//第四步删除当前页面dom结构
let list = $(".lnk_code");
for (let k = 0; k < list.length; k++) {
if (list[k].innerHTML === j) {
list[k].parentElement.remove();
}
}
$("#box1").hide();
$("#cover").css("cssText", "background:");
$("#create").removeAttr("disabled");
$(".delete").removeAttr("disabled");
}
//选择的客户端变化时
function clientChange() {
//获取端口url
let myselect = document.getElementById("weburl");
let index = myselect.selectedIndex;
let weburl = myselect.options[index].value;
let lastnum = $(".table tr:last").find(".lnk_code").text();
let ind = 1
if (lastnum !== '') {
ind = parseInt(lastnum) + 1;
}
if (weburl === "pharmacy") {
if (ind == 1) {
$("#lnkName").val("钜星科技便民问诊系统-门店端");
$("#cachePath").val("default");
} else {
$("#lnkName").val("钜星科技便民问诊系统-门店端" + ind);
$("#cachePath").val("pharmacy-" + ind);
}
} else if (weburl === "doctor") {
$("#lnkName").val("钜星科技便民问诊系统-医生端" + ind);
$("#cachePath").val("doctor-" + ind);
} else {
$("#lnkName").val("钜星科技便民问诊系统-药师端" + ind);
$("#cachePath").val("pharmacist-" + ind);
}
}
//创建按钮点击事件
$("#create").click(function () {
$("#box").show();
$("#cover").css("cssText", "background:#aaa");
//禁用创建和删除按钮
$("#create").attr("disabled", "disabled");
$(".delete").attr("disabled", "disabled");
let lastnum = $(".table tr:last").find(".lnk_code").text();
let ind = 1
if (lastnum !== '') {
ind = parseInt(lastnum) + 1;
}
if (ind == 1) {
$("#lnkName").val("钜星科技便民问诊系统-门店端");
$("#cachePath").val("default");
} else {
$("#lnkName").val("钜星科技便民问诊系统-门店端" + ind);
$("#cachePath").val("pharmacy-" + ind);
}
//点击创建按钮首先清楚所有的选项,然后加载端口选项
$("#weburl").empty();
loadPortSet();
});
//创建快捷方式
function createInk() {
//获取端口url
let myselect = document.getElementById("weburl");
let index = myselect.selectedIndex;
let weburl = myselect.options[index].value;
//获取快捷方式名称
let InkName = $("#lnkName").val().trim();
//获取缓存文件夹名称
let cacheDir = $("#cachePath").val().trim();
//第一步创建桌面快捷方式
setlnk(InkName, weburl, cacheDir);
//第二步将数据添加到setting.json文件中
let lastnum = $(".table tr:last").find(".lnk_code").text();
let itemNum = 1;
if (lastnum != "") {
itemNum = parseInt(lastnum) + itemNum;
}
let thisItem = {};
if (weburl === "pharmacy") {
thisItem.client = "门店端";
} else if (weburl === "doctor") {
thisItem.client = "医生端";
} else {
thisItem.client = "药师端";
}
thisItem.lnk_url = desktop + dpth.sep + InkName + ".lnk";
thisItem.cache_dir = cacheDir;
lnkList[itemNum] = thisItem;
let jsonstr = JSON.stringify(lnkList);
fs.writeFileSync(lnks_url+dpth.sep+"lnks.json", jsonstr, function (err) {
log.error("创建快捷方式,写入文件失败!" + err);
});
$("#box").hide();
$("#cover").css("cssText", "background:");
$("#create").removeAttr("disabled");
$(".delete").removeAttr("disabled");
let list = $(".lnk_code");
for (let k = 0; k < list.length; k++) {
list[k].parentElement.remove();
}
loadLnkList(lnkList);
}
//
function setlnk(lnkname, targetUrl, cacheDir) {
//查看当前文件夹目录
let thisurl = location.href;
thisurl = thisurl.substring(8, thisurl.lastIndexOf("resources") - 1);
if(fs.existsSync(desktop + dpth.sep + lnkname + ".lnk")){
fs.unlinkSync(desktop + dpth.sep + lnkname + ".lnk");
}
//获取当前文件的绝对路径
ws.create(desktop + dpth.sep + lnkname + ".lnk", {
args: targetUrl + "--" + cacheDir,
//打包时修改exe文件路径
target: decodeURIComponent(thisurl) + dpth.sep+"钜星科技便民问诊系统.exe",
runStyle: ws.MIN,
desc: "钜星科技便民问诊系统"
}, function (err) {
if (err) {
console.log("创建快捷方式出错:" + err);
}
});
}
function exit() {
$("#box").hide();
$("#cover").css("cssText", "background:");
$("#create").removeAttr("disabled");
$(".delete").removeAttr("disabled");
}
function exit1() {
$("#box1").hide();
$("#cover").css("cssText", "background:");
$("#create").removeAttr("disabled");
$(".delete").removeAttr("disabled");
}
//选择下拉框填充
function loadPortSet() {
//加载到下拉框中
let str = "<option value='pharmacy'>门店端</option>";
str = str + "<option value='doctor'>医生端</option>"
str = str + "<option value='pharmacist'>药师端</option>"
$("#weburl").append(str);
}
//加载已创建的程序快捷方式
function loadInit(respath,lnks_url) {
log.info("快捷方式数据存放目录:"+lnks_url);
if(!fs.existsSync(lnks_url)){
fs.mkdirSync(lnks_url);
fs.writeFileSync(lnks_url+dpth.sep+"lnks.json", JSON.stringify({}), function (err) {
});
}
$.getJSON(lnks_url+dpth.sep+"lnks.json", function (data) {
if (!$.isEmptyObject(data)) {
loadLnkList(data);
lnkList = data;
}
});
}
//加载存在快捷方式
function loadLnkList(data) {
$.each(data, function (i, item) {
let str = "<tr>";
str = str + "<td class='lnk_code'>" + i + "</td>";
str = str + "<td>" + item.client + "</td>";
str = str + "<td>" + item.lnk_url + "</td>";
str = str + "<td>" + item.cache_dir + "</td>";
let lnk_name=item.lnk_url.substring(item.lnk_url.lastIndexOf(dpth.sep)+1);
let type=null;
if(item.client=="门店端"){
type="pharmacy"
}else if(item.client=="医生端"){
type="doctor"
}else{
type="pharmacist"
}
str = `${str}<td><input type='button' onclick='setlnk("${lnk_name}","${type}","${item.cache_dir}")' class='btn btn-success' value='重创快捷方式'/></td>`;
str = `${str}<td><input type='button' onclick='deleteLnk("${i}" , "${lnk_name}")' class='btn btn-danger delete' value='删除'/></td>`;
str = str + "</tr>"
$(".table").append(str);
});
}
</script>
</body>
</html>

BIN
static/images/clear.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

BIN
static/images/copy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 B

BIN
static/images/cut.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 B

BIN
static/images/exit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

BIN
static/images/justar.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
static/images/paste.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 B

BIN
static/images/refresh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 B

BIN
static/images/search.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

2073
yarn-error.log Normal file

File diff suppressed because it is too large Load Diff

2017
yarn.lock Normal file

File diff suppressed because it is too large Load Diff