diff --git a/docs/install.md b/docs/install.md index c694356e..799f16b7 100644 --- a/docs/install.md +++ b/docs/install.md @@ -22,6 +22,26 @@ rm scanservjs.tar.gz rm -r scanservjs ``` +## Troubleshooting + +Scanservjs works by wrapping CLI calls to `scanimage` as the user `scanservjs` +which is a member of the `scanner` group. If connected by USB then we ultimately +need access to some hardware and that access may not be granted by default. To +debug where the problem is: + +* First, check that you've followed the instructions [here](./sane.md). +* Try running `sudo scanimage -L` (for diagnostic purposes) - this really should + work. If it doesn't, then it's most likely a SANE / driver related issue. +* Now try running as a normal user without sudo: `scanimage -L`. If you've + installed scanservjs then there should be a `scanservjs` user. Try the same + command as that user: `sudo su - scanservjs -c 'scanimage -L'`. If this + doesn't show your scanner then most likely you need a udev rule (see + [here](./sane.md)) to allow certain groups access to the hardware - but it's + also worth verifying that the `scanservjs` user is a member of the `scanner` + group (or the group specified in your udev rule): `groups scanservjs`. +* Getting logs: use `journalctl`. See the journalctl manpage for details but + `sudo journalctl -e -u scanservjs` should be enough to get you started. + ## Old Debian For more on problems installing an up to date nodejs on Debian which includes `npm`. See diff --git a/server/bin/install.sh b/server/bin/install.sh index 3efb564a..e5c3be8a 100644 --- a/server/bin/install.sh +++ b/server/bin/install.sh @@ -96,4 +96,4 @@ systemctl start scanservjs echo "scanservjs starting" echo "http://127.0.0.1:8080" echo -echo "If you have problems, try 'journalctl -xe'" +echo "If you have problems, try 'sudo journalctl -e -u scanservjs'" diff --git a/server/package-lock.json b/server/package-lock.json index 6dc07119..c944286f 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -1,6 +1,6 @@ { "name": "scanservjs-server", - "version": "2.8.3", + "version": "2.8.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/server/package.json b/server/package.json index e53c4e1a..5142df46 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "scanservjs-server", - "version": "2.8.3", + "version": "2.8.4", "description": "scanservjs is a simple web-based UI for SANE which allows you to share a scanner on a network without the need for drivers or complicated installation. scanserv does not do image conversion or manipulation (beyond the bare minimum necessary for the purposes of browser preview) or OCR.", "scripts": { "serve": "nodemon --exec 'vue-cli-service serve'", diff --git a/server/src/configure.js b/server/src/configure.js index 0a7968f5..a5ea6a64 100644 --- a/server/src/configure.js +++ b/server/src/configure.js @@ -1,3 +1,4 @@ +const express = require('express'); const fs = require('fs'); const rootLog = require('loglevel'); const prefix = require('loglevel-plugin-prefix'); @@ -10,10 +11,14 @@ rootLog.setLevel(Config.log.level); prefix.apply(rootLog, Config.log.prefix); const log = rootLog.getLogger('Http'); -const bodyParser = require('body-parser'); const Api = require('./api'); -const sendError = (res, code, data) => { +/** + * @param {import('express').Response} res + * @param {number} code + * @param {any} data + */ +function sendError(res, code, data) { let content = { message: '' }; @@ -25,9 +30,12 @@ const sendError = (res, code, data) => { content.message = data; } res.status(code).send(content); -}; +} -const logRequest = (req) => { +/** + * @param {import('express').Request} req + */ +function logRequest(req) { const properties = ['method', 'path', 'params', 'query', 'body']; const output = {}; for (const property of properties) { @@ -40,9 +48,12 @@ const logRequest = (req) => { } } log.debug('request: ', output); -}; +} -const initialize = (rootPath) => { +/** + * @param {string} rootPath + */ +function initialize(rootPath) { if (rootPath) { // Only required for running in development Object.assign(Config, { @@ -54,17 +65,24 @@ const initialize = (rootPath) => { }); } - fs.mkdirSync(Config.outputDirectory, { recursive: true }); - fs.mkdirSync(Config.tempDirectory, { recursive: true }); -}; - -module.exports = (app, rootPath) => { + try { + fs.mkdirSync(Config.outputDirectory, { recursive: true }); + fs.mkdirSync(Config.tempDirectory, { recursive: true }); + } catch (exception) { + log.warn(`Error ensuring output and temp directories exist: ${exception}`); + log.warn(`Currently running node version ${process.version}.`); + } +} + +/** + * Configures express + * @param {import('express').Express} app + * @param {string} rootPath + */ +function configure(app, rootPath) { initialize(rootPath); - app.use(bodyParser.urlencoded({ - extended: true - })); - - app.use(bodyParser.json()); + app.use(express.urlencoded({ extended: true })); + app.use(express.json()); app.get(['/context', '/context/:force'], async (req, res) => { logRequest(req); @@ -141,6 +159,6 @@ module.exports = (app, rootPath) => { sendError(res, 500, error); } }); +} - app.use(bodyParser.json()); -}; +module.exports = configure; diff --git a/webui/src/classes/constants.js b/webui/src/classes/constants.js index 5ed4a8b7..b348e52b 100644 --- a/webui/src/classes/constants.js +++ b/webui/src/classes/constants.js @@ -2,6 +2,7 @@ const Constants = { Version: process.env.VUE_APP_VERSION, Locales: [ + 'cn', 'cz', 'de', 'en', diff --git a/webui/src/locales/cn.json b/webui/src/locales/cn.json new file mode 100644 index 00000000..f17d1d0d --- /dev/null +++ b/webui/src/locales/cn.json @@ -0,0 +1,89 @@ +{ + "global": { + "application-name": "scanservjs" + }, + + "about": { + "main": "scanservjs 是一个基于网页的扫描仪UI。 它可以实现在局域网内共享一个或多个扫描仪(用SANE实现)而免去繁复的驱动安装。 扫描的文件可保存为 TIF, JPG, PNG, PDF 和 TXT (使用Tesseract OCR) 等格式,并可配置多种压缩率。 它亦支持多页扫描以及所有与SANE兼容的设备", + "issue": "反馈问题或查看源码" + }, + + "batch-dialog": { + "btn-finish": "完成", + "btn-rescan": "重新扫描", + "btn-next": "下一张" + }, + + "files": { + "filename": "文件名", + "date": "日期", + "size": "大小", + "message:deleted": "已删除" + }, + + "navigation": { + "scan": "扫描", + "files": "文件", + "settings": "设置", + "about": "关于", + "version": "版本" + }, + + "pipeline": { + "high-quality": "高画质", + "medium-quality": "中画质", + "low-quality": "低画质", + "uncompressed": "无压缩", + "lzw-compressed": "LZW 压缩", + "ocr": "OCR", + "text-file": "文本文件" + }, + + "scan": { + "device": "设备", + "source": "来源", + "resolution": "分辨率", + "mode": "模式", + "dynamic-lineart": "动态线性", + "dynamic-lineart:enabled": "开启", + "dynamic-lineart:disabled": "关闭", + "batch": "批量", + "batch:none": "无", + "batch:manual": "手动 (有提示)", + "batch:auto": "自动 (进纸器)", + "batch:auto-collate-standard": "自动 (标准校对 1, 3... 4, 2)", + "batch:auto-collate-reverse": "自动 (逆向校对 1, 3... 2, 4)", + "filters": "滤镜", + "filters:auto-level": "自动调整", + "filters:threshold": "阈值", + "filters:blur": "模糊", + "format": "格式", + "btn-preview": "预览", + "btn-clear": "清除", + "btn-scan": "扫描", + "btn-reset": "重置", + "top": "上边距", + "left": "左边距", + "width": "宽度", + "height": "高度", + "brightness": "亮度", + "contrast": "对比度", + "message:loading-devices": "加载设备 ...", + "message:no-devices": "未找到设备", + "message:deleted-preview": "删除预览", + "message:turn-documents": "旋转", + "message:preview-of-page": "预览" + }, + + "settings": { + "title": "@:navigation.settings", + "behaviour-ui": "用户界面", + "locale": "语言", + "locale:description": "选择语言", + "theme": "主题", + "theme:description": "界面主题。 若切换主题,请重新加载页面。", + "theme:system": "系统默认", + "theme:light": "浅色", + "theme:dark": "深色" + } +} \ No newline at end of file diff --git a/webui/src/styles/variables.scss b/webui/src/styles/variables.scss index 79ff7369..2d950ffa 100644 --- a/webui/src/styles/variables.scss +++ b/webui/src/styles/variables.scss @@ -1,2 +1,2 @@ -$body-font-family: 'Segoe UI', 'Roboto', 'San Francisco', 'Lucidabright', 'Helvetica'; +$body-font-family: 'Segoe UI', 'Roboto', 'Lucida Grande', 'San Francisco', 'Lucidabright', 'Helvetica'; $navigation-drawer-border-width: 0;