Skip to content

基于electron、react、redux、webpack、typescript、express、mongodb的智能财务系统

Notifications You must be signed in to change notification settings

northeast250/finance-steward-GUI

Repository files navigation

智能财务系统开发笔记

[TOC]

南川,2021年4月

项目概况

TODO

  • 增加本地上传功能(以对OpenAPI进行测试)
  • 研究mongoose -> swagger的实现
  • 对分类结果与图片的本身标注做对比分析
  • 进一步解决只识别出部分条目的图片问题(打算先以识别出小于3条的流水类图片着手分析)
  • 进一步解决未分类成功的问题
  • 对详情类图片做进一步的检验(因为这个相较于流水类更难捕捉出错误)
  • 对分类的所有结果进行统计分析
  • 增加对其他类型,例如图片等文件的导入支持(暂无需求)

Finished

  • 解决react的热更新问题(已基于webpack serve实现)
  • 解决electron的热更新问题(已基于electron-reloader实现)
  • 增加对cssless等文件的导入支持(已基于style-loadercss-loaderles-loaderwebpack中实现)
  • 修复由于redux-thunk导致的reduxcreateStore时出现typescript警告的问题(这个问题最令我惊奇的是使用//@ts-ignore都无法屏蔽……不过本质上是因为combinedReducers用到了一个特有Symbol$CombinedState,反正挺蛋疼,我暂时先在tsconfig.json配置里把declarationdeclarationMap关了,就没问题了,这个ts选项我暂时也用不到。)
  • 基于以上对redux-thunk的修复,进一步寻找一个优秀的typescipt+redux的编码约定(目前我把所有的actionTypes写在一个文件里,然后在actions文件里写同步(直接返回Action)或者异步(thunk)代码,其中thunk不走reducer,同时还要把thunk中间件放在logger中间件的前面。另外,我不再考虑既声明ActionType又声明Action的问题了,对于Action直接使用AnyAction(默认自带type属性),对于ActionType直接使用switch(action.type as XXActionType)代码约定,我觉得挺好的。日后再研究其他大佬的代码吧~)

UI

image-20210419222746653

链接:

框架

  • Electron
  • React
  • Redux
  • TypeScript
  • Webpack

开发日志

2021年05月04日

mongoose lean with string type of ObjectId

官方lean描述:

而将lean结果中的ObjectId转成string,可以通过使用以下插件:

2021年04月23日

  • 完成云端数据库的重新安装、配置

2021年04月22日 完成代码的重构、初步搭建了API

彻底重构了代码,所有接口均重新统一定义,接口、视图、算法、配置、自动脚本高度模块化。

image-20210422235233650

2021年04月18日 第一版UI

image-20210419222746653

V0.0.1 概况

按照准确度标准,目前成功分类情况如下,错误率在20%左右:

image-20210418194124073

现一一进行错误修复。

场景1: 详情页的标题有两行导致序列化失败

image-20210418194852184

根据程序识别,另一种有两行(讨论过)的情况,就是当logo里有字的时候,比如如下:

image-20210418200717576

所以程序可以设置两条逻辑,即当金额与详情隔着两行的时候,通过判定两行的长度去分析属于哪一类,尤其对于第二类,考虑限制在字数五个以下。

经过如上处理后,已经只有10%左右错误率了。

image-20210418201149302

场景2 最左边一栏有图标,导致序列化失败或者效果变差

image-20210418201632617

根据位置计算:图标位170,图宽965,比例为0.176,以上下浮动2个点算,如果我们发现低于屏幕宽度15%的文字识别,则可以视为非流水解析部分。

image-20210418202005652

目前来看,应该没此类问题了,不过错误更多了,应该是发现了之前没发现的错误。目前错误率在15%左右。

image-20210418203421441

场景3 没截图截全的暂不处理

image-20210418203400840

场景4 有浮窗的暂不处理(根据之前的讨论,后续没有浮窗问题了)

image-20210418203605975

场景5 没有交易对象

image-20210418203730759

场景6 截图不全,这个图其实已经识别出了数字,但是由于没有上面的标题,所以归为了场景5,但其实是用户自己的操作问题,所以这种也不考虑

image-20210418204423851

场景7 带千分位金额未有效匹配

image-20210419210009532

这张图至少暴露了两个问题,一个是有一些字没有匹配,比如“其他”。(下一个场景说明)

另一个就是带千分位金额没有匹配成功。

第二个问题较为简单,可以先处理一下。

第一种问题之后统一处理(比如用聚类)

场景8 支付宝的“其他”未成功匹配

image-20210419210916197

尽管这个“其他”没有匹配出来让我们很头疼,但是仔细分析,依旧有转机。

可以看到,这张截图里,匹配出来4条,一共6,剩余2条就是“其他”,然后确信度为三分之二,正是4除以6。

造成这样的原因,主要是因为,我们支付宝的匹配依据是日期与金额相距为2,而微信是相距为1,当“其他”未匹配成功时,就被微信模式匹配上了,于是最终出来匹配出4个支付宝、2个微信的局面。

解决的办法也就呼之欲出了,我们对于没有达到百分之百确信度的流水匹配,将他们全部转成支付宝就好。

也许会有误判,但可能性不高,我们可以做如下判断,如果支付宝匹配数大于微信,则将微信部分全部转成支付宝,否则程序报错,我们检查一下。

场景9 标题过长,与金额连在了一起,导致识别失效

image-20210419212328900

我们可以通过识别框的宽度(是否超过屏幕宽度的百分之80),并且有省略号、最后是数字,等综合确定,以进行分割预处理。

V0.0.1 总结

经过对以上问题的分析与处理后,目前已经去除了以上类型的问题。

image-20210419220729820

当然,这肯定不能表示已经没有错误了,事实上还有一些隐藏的错误,比如实际有多条,但只识别出一两条,并且还报对。这些留待下一版解决。

最后,再给出一下,经过标注系统处理后,剩余的一些未能进入分类算法的图片集合:

image-20210419220718316

文字版如下,如有必要可以检验,大部分是由于截图不全,少部分是因为浮窗之类无需深入解决的问题:

{
  "微信/商户消费/详情页无商户全称/美团点评&京东&拼多多平台商户、理财产品/有优惠/支出/交易名称:对方名称/当前状态:支付成功/xq1.jpg": "有浮窗(跳过)",
  "微信/商户消费/详情页内容齐全/付款码、乘车码、微信小程序、第三方APP、手机充值、公众号打赏/无优惠/退款/当前状态:已全额退款/ls1.jpg": "未分类成功(跳过)",
  "微信/商户消费/详情页内容齐全/付款码、乘车码、微信小程序、第三方APP、手机充值、公众号打赏/无优惠/退款/退款状态:已退款/ls3.jpg": "未分类成功(跳过)",
  "微信/商户消费/详情页内容齐全/付款码、乘车码、微信小程序、第三方APP、手机充值、公众号打赏/有优惠/支出/当前状态:支付成功/ls3.jpg": "未分类成功(跳过)",
  "支付宝/余利宝/转入/交易名称:商品说明/当前状态:交易成功/ls1.jpg": "未分类成功(跳过)",
  "支付宝/余利宝/转入/交易名称:转出说明/当前状态:交易成功/ls1.jpg": "未分类成功(跳过)",
  "支付宝/余利宝/转出/交易名称:转出说明/当前状态:交易成功/ls1.jpg": "未分类成功(跳过)",
  "支付宝/余利宝/转出/交易名称:转出说明/当前状态:交易成功/ls2.jpg": "未分类成功(跳过)",
  "支付宝/余额/充值/交易名称:余额充值/当前状态:交易成功/ls1.jpg": "未分类成功(跳过)",
  "支付宝/余额/提现/交易名称:余额提现/当前状态:交易成功/ls1.jpg": "未分类成功(跳过)",
  "支付宝/余额宝/收益/交易名称:商品说明主要部分/当前状态:交易成功/ls1.jpg": "未分类成功(跳过)",
  "支付宝/余额宝/转入/交易名称:商品说明/当前状态:交易关闭/ls1.jpg": "未分类成功(跳过)",
  "支付宝/余额宝/转入/交易名称:商品说明/当前状态:交易关闭/ls2.jpg": "未分类成功(跳过)",
  "支付宝/余额宝/转入/交易名称:商品说明/当前状态:交易成功/ls4.jpg": "未分类成功(跳过)",
  "支付宝/余额宝/转出/交易名称:商品说明/当前状态:交易成功/ls1.jpg": "未分类成功(跳过)",
  "支付宝/余额宝/转出/交易名称:转出说明/当前状态:交易成功/ls1.jpg": "未分类成功(跳过)",
  "支付宝/小钱袋/转入/交易名称:商品说明/当前状态:交易成功/ls1.jpg": "未分类成功(跳过)",
  "支付宝/小钱袋/转入/交易名称:商品说明/当前状态:等待付款/ls1.jpg": "未分类成功(跳过)",
  "支付宝/小钱袋/转出/交易名称:商品说明/当前状态:交易成功/ls1.jpg": "未分类成功(跳过)",
  "支付宝/线上交易/多出汇率(国外网站交易)/支出/交易名称:商品说明/当前状态:交易成功/ls1.jpg": "未分类成功(跳过)"
}

此外,目前系统预设的流程相关的图片标注分类如下,未来将继续补充完善:

export const PRESET_MARK_TYPES = [
  "已完全识别",
  "未分类成功(跳过)",
  "截图不全(跳过)",
  "有浮窗(跳过)",
  "延后处理",
];

框架相关 - 开发经验

遇到需要确认安装webpack-dev-server

直接按Y确认即可,或者提前在本地全局安装好:

npm install -g webpack-dev-server

遇到安装过程中出错的问题

可能是因为网络原因,可以重新安装一遍,或者继续安装未安装成功的那个包

关于documentwindow等非关键依赖,WebStorm cannot find name的问题

重新配置WebStorm里typescript所使用的的位置与版本:

WebStorm > Preference > Language & FrameWorks > Typescript > Typescript

选择自己本地全局安装的Typescript(注意先更新到最新版,目前是4.2.4+),不要选用项目初始化的内置Typescript

如何用webpack打包cssless

webpack的交互对象是js文件,需要通过其他loader将特定格式的文件转成js文件处理。

对于css文件,可以先通过css-loader转成css信息的js数组格式,这个时候css其实已经导入了,但是尚未能够生效在目标网页上。

而实现后一步操作的,就是style-loader,它们将这些编译后的js格式的css信息进一步插入到网页的style标签内(这也就是style-loader取名之意)。

而对于其他格式,比如lesssass等,则可以先将它们转成css格式,要么直接用特定的loader,比如对于less文件可以使用lees-loader,要么可以用postcss处理(此项目只用了less-loader,[todo]: postcss有点复杂,日后再更)。

其配置如下:

[
  {
    test: /\.css$/,
    use: [{ loader: "style-loader" }, { loader: "css-loader" }],
  },
  {
    test: /\.less$/,
    use: [
      { loader: "style-loader" },
      { loader: "css-loader" },
      { loader: "less-loader" },
    ],
  }
]

如何在webpack.config.js中使用ESM(即importexport

在学习一个好项目:https://github.com/electron-react-boilerplate/electron-react-boilerplate 的时候,发现他里面的所有webpack配置文件都用了ESM,非常好奇他的实现,因为我把自己的webpack配置文件从CMJ改成ESM后就无法运行了。

后来经过大量测试,以及结合这篇QA:https://stackoverflow.com/questions/31903692/how-can-i-use-es6-in-webpack-config-js/67136670#67136670 ,终于找到了自己的解决方案,那就是 echo '{"presets": ["@babel/preset-env"]}' > .babelrc g 此外,还得安装一下babel的相关依赖: yarn add -D @babel/core @babel/register @babel/preset-env

最后,将webpack.config.xx.js改成webpack.config.xx.babel.js即可。

这是一项很有收获的经验。

如何顺利执行基于typscriptelectron

结合一些资料,可以知道有两种办法。 第一种,是使用tsc进行预编译,然后再用electron运行。 其具体命令如下: tsc ./src/main/index.ts && electron ./src/main/index.js

这里比较关键的是,tsc执行完成后会生成.js文件,然后electron运行这个.js文件即可。

但也存在问题,如果使用tsc -w命令监视index.ts文件,则当我们修改源代码时,虽然会实时地重新编译,但是由于我们electron已经加载了原来的.js文件,因此无法做到electron的热更新。

此外,有资料指出,这种先编译的开销较大。

第二种,也是本项目(参考的electron-react-boilerplate)所选用的方法,就是将.ts文件交给babel处理,babel只处理其中涉及到ts相关的部分,编译转换的开销较小。

在上一个章节,我介绍了如何在webpack配置中使用ESM的办法,具体就是使用babel,结合.babelrc文件。不过那次我们只需要处理ESMimportexport,因此只需要@babel/preset-env即可,但这次我们要处理typscript,因此还需加上@babel/preset-typescript(顺便还要安装一下)。

不过还没完,还得加上一个babel_register的脚本,在运行renderer中不需要加是因为有webpack serve帮我们搞定了,但运行electron我们是纯babel,所以需要自己预处理.ts相关文件。

另外有趣的一点是,基于tsc编译后的每个.ts文件都有一个对应的.js文件,而通过babel编译后的每个.ts文件都对应两个额外文件:.d.ts.d.ts.map

如何结合mainrenderer进行打包渲染?

第一种方法,是将mainrenderer独立开来。 先用webpack servereact组件渲染到localhost,然后再用electron里的loadUrl函数渲染main。实践证明,由于编译、渲染需要耗时,以及webpack serve是一个堵塞操作,不方便在script里进行顺序控制,所以我需要在loadUrl函数里写一个轮询,直到渲染成功后才正常加载。

这个方法比较笨拙,但是容易理解。基于这个理解之后,再来看第二种方法,它的本质也是两个独立进行,但是基于webpack的一些默认参数,做到了更好的进程间通信(于是就不用轮询了,降低了对业务代码的入侵)。

核心就是直接启动renderer进行,但是在renderer的配置文件里,加上devServer选项,核心配置如下,在before参数里使用spawn开启了一个新的进程,实在awesome~:

devServer: {
	before()
	{
		console.log('Starting Main Process...');
		spawn('npm', ['run', 'start:main'], {
			shell: true,
			env: process.env,
			stdio: 'inherit',
		})
		.on('close', (code) => process.exit(code))
		.on('error', (spawnError) => console.error(spawnError));
	}
}

另外,这里的.on('close')回调函数,也解决了如果独立运行两个进行,则关闭electron进程后webpack serve进程仍然会无意义进行的问题。

加载index.html的不同办法

index.html是必须要有的,至少有一个id=app之类的结点,问题是如何加载、编译与转换。

第一种方案,我们把index.html里要引用的script都写死,比如一般来说我们会将bundle.js打包到根目录下的dist/中,如果我们index.html在根目录下,则直接写死<script src="./dist/bundle.js"></script>即可。

这样,当webpackreact组件打包到dist/目录下后,这个index.html页面就可以展示react组件了(同时不要忘了引入reactreact-dom的脚本文件)。最后,再由electron读取这个index.html文件,就能做到在electron中渲染。

但这种方案有个明显的缺点,那就是生成的dist文件中不含有index.html文件,这不适合项目的发布。所以,我个人还是推荐index.html得提前拷贝到目标路径吧dist/下,然后对bundle.js文件的引用就是./bundle.js了。

那么要实现这个拷贝,也至少有两个方法,第一种比较朴素,那就是每次运行renderer进程时将index.htmlcp(linux、mac)或者copy_file(需要安装,全平台)拷贝到dist/目录下(同样要包含reactreact-dom脚本)。

还有一种办法就比较智能,那就是使用webpackhtml-webpack-plugin插件,它会自动将index.html拷贝到目标位置,并且还会自动加上其依赖(也就是说,不需要手动写引入bundle.jsreact.jsreact-dom.js等)。此外,它还需要热更新功能,可谓一举双得,不过这会覆盖devServer里的hot选项。

electron如何热更新

  • 即使是electron-react-boilerplate也不支持electron的热更新,hh,得找其他库看看实现原理,估计都用到了electron-reload吧,不过这个也不重要,重要的还是renderer部分的热更新。

然而很简单,只需要安装electron-relaoder后在electron的主程序里加三句话即可:

try {
	require('electron-reloader')(module);
} catch {}

它的原理,就是会自动寻找入口文件的依赖图,然后对其进行文件修改监测,一旦有确认修改就重启。

不过副作用就出现在这里,我们之前配置rendererwebpack部分时,加了一句:

on('close', (code) => process.exit(code))

这一句代码会导致,当我们的electron程序关闭后自动关闭渲染进程,所以我们要删掉这一行。

(理论上renderer进程是electron进程的子进程,但是我们的webpack配置结果就是electron进程是renderer进程的子进程,目前来看没有太大问题,我不确定如果我们反过来是否就是把before改成after就完事了,但好像改的意义也不是特别大)

关于electron-reloader可以参考:

业务相关 - 开发经验

如何将OCR的结果显示在图片上,并且支持缩放

第一种方法,也是一开始采取的方法,比较笨拙。

那就是先求出预定的缩放比率,然后将图片按比例放缩,再讲OCR的矩形坐标按照比率进行计算再叠加渲染。

我一直觉得这个方法很笨拙,但当时时间有限、技术有限,所以只好用了这个方案。

第二种方法,图形本身不做缩放,OCR结果直接叠加渲染到图片上,最后将这个整体使用以下CSS进行缩放:

.img-with-ocr {
	transform: scale(SCALE);
	transform-origin: top left;
	height: IMG_HEIGHT * SCALE;
}

这里的IMG_HEIGHT就是图片的实际高度,而SCALE就是目标缩放比率,由于我需要的图片布局就是统一宽度,高度按比率缩放,所以SCALE这么设计。这里之所以还要对这个形状的高度本身做限制,是因为我这个容器就是顶层容器,但是缩放效果是不改变容器大小的,因此会出现缩放后的效果与容器不贴合的副作用,因此还需要重设容器大小。

这样,通过一个统一的缩放参数,就优化了第一种方案中需要计算2 + 4 * N遍的问题。此外,这种通过CSS里的scale参数去控制显示的缩放比率,还是非常有用的!(在此,感谢威盛项目,这个技巧便是在这个项目中摸索出来的。)

关于热开发读取文本导致重启的问题

很奇怪,当我把数据缓存到和mainrenderer同级的data文件下时,会导致renderer重启,但当我把它放进main里面则不会,实在不清楚webpack热重启到底依赖了哪些,它是整个src文件夹都做了监控吗?

最后终于找到问题了,原来不是webpack的锅,而是electron-reloader,具体见:

// 开发模式使用electron热重载,它会自动构建依赖图
// 一定要小心这里要监测的范围,由于我们修改electron主要是一些程序部分,所以千万不要把需要不断覆写的数据文件也加进来,不然会一直重载
// 这里的启示是要把数据文件独立出去,比如放在与`main`同级的`data`文件夹下,然后只监控`main`文件夹
try {
  require("electron-reloader")(__dirname);
} catch {}

关于相对路径、绝对路径、固定路径

从相对路径到绝对路径,我们已经很熟悉了,比如使用path.resolve之类的函数。

然而当我们的程序涉及到了打包、移动,那么问题就蹊跷起来了。

事实上,我通过这种方式将数据文件夹的相对路径指定成绝对路径之后,打包完直接到了electron/dist下的未知名路径,所以事实上产生了错误。

有趣的是,在renderer里会有这样的错误,但在main里没有,毕竟,其实只有renderer里的资源被打包了,main程序里的路径是不变的。

基于此,有两种方案,一种是所有的本地资源读取都在main里,另一种就是把路径写死这样两个进程里都可以使用了,毕竟,所谓的web secruity有时间再研究吧,我现在就是要在renderer里大用特用node!将业务效率MAX MAX MAX

关于初始化对象并复用的问题

export const _initTokenLS: TokenLS = {
  items: [],
  tokens: [],
  scenario: Scenario.unknown,
  cntWxTokens: 0,
  cntZfbTokens: 0,
  confidence: 0,
}

这是一个常量对象,用于初始化,然而,却隐藏着难以预估的bug。

问题就在于,虽然我们用const修饰符固定住了变量,所以不能用赋值语句修改_initTokenLS这个变量,然而,这并不能阻止我们尝试修改它子属性的行为(用C++术语理解,就是指针是常量,但是指针指向的变量不是常量)。

于是乎,当我用这个常量作为很多其他变量的初始值,并在其上做修改,例如如下:

let tokenLS: TokenLS = _initTokenLS;
tokenLS.confidence = 1; // _initTokenLS.confidence = 1

这样,对tokenLS的修改实质上等价于对_initTokenLS的修改,问题就连锁式的、反复的产生了。

所以,要么,我们铭记,初始化的常量,不能直接赋值,比如可以用解构语法,写成这样(等价于C++中的复制构造):

let tokenLS: TokenLS = {..._initTokenLS}

但是我们也许当时记得,后续难免会疏忽,那有没有规避对对象的修改操作的办法呢?倒也不是没有,比如可以用typscript进行对象的键值限制:

image-20210419202741257

然而,这样的问题有三:

  1. 虽然对象里面的每个键itemsconfidence等不可以被修改(重新赋值)了,但是依旧可以使用一些原型操作(比如当键是一个对象的时候),所以这个解决方案并没有本质上解决问题
  2. 尽管我们可以通过种种复杂的手段,限定初始化对象的修改操作,但是我们依旧会难免不甚使用赋值操作以初始化另一个变量,当我们主动或被动(IDE提醒)意识到这个对象不可以直接修改(而是需要解构赋值)后为时已晚
  3. 为了这个初始化对象,我们还需要多写一个一次性的接口,简直浪费。

所以另一种绝佳的办法就是写成一个初始化的函数:

export const initTokenLS = (): TokenLS => ({
  items: [],
  tokens: [],
  scenario: Scenario.unknown,
  cntWxTokens: 0,
  cntZfbTokens: 0,
  confidence: 0,
});

这样,我们每次直接调用,赋值、修改都不会影响初始化的结果:

let tokenLS: TokenLS = initTokenLS();
tokenLS.confidence = 1; // next time, the initial tokenLS2.confidence = 0 still

写到此,使用函数的优越性就彰显出来了,这似乎,从另一个角度理解了,为什么在redux里把各种action写成函数要比写成对象方便的多了,或许,问题的关键就在此文中。

关于webpack打包过程中出现的关于node的warning

问题貌似产生于,npmyarn混用。 昨晚(2021年04月20日)我用yarn安装chai最后总是卡住,不断retry,最后用npm安装好了。

我观察到,这个包貌似有很多依赖相关,这可能导致了我的环境发生了变化,在那之后,貌似我在运行webpack的打包程序时,就会出现这样的一个警告:

Use the `--scripts-prepend-node-path` option to include the path for the node binary npm was executed with

最后参考这篇文章: 我想问一下这个问题怎么解决,谢谢!_慕课猿问 得到了解决,方案就是运行如下:

yarn config set scripts-prepend-node-path true

运行express的一些指令

{
  "build:api": "tsoa spec-and-routes && tsc --experimentalDecorators --esModuleInterop --resolveJsonModule --outDir build src/api/server.ts",
}

关于ts-node运行异常(耗时两小时)

比如运行A函数,结果完全不符合预期,甚至是其他函数的结果,这种情况一定是map出问题了!

用我们的ts-node scripts/clear_non-ts-files.ts脚本清除一下这些map就正常了!

关于populateObjectID的问题

当我们封装了一些CURD的接口后,返回的字段是否包含populate的信息,具体的说,是返回了一个_idstring还是一个object,这是个问题,需要脑子清醒!

不然会报can't cast xx to .... @path之类的错误,值得注意。

另外,集成swagger时发现无法识别OID类型(即mongoose.Schema.Types.ObjectID),所以后来就把ObjectID都改成string了。

MongoDB配置

卸载mongodb

参考:https://m.yisu.com/zixun/146420.html

sudo yum erase $(rpm -qa | grep mongodb-org) #卸载MongoDB
sudo rm -r /var/log/mongodb #删除日志文件
sudo rm -r /var/lib/mongo  #删除数据文件

安装mongodb

参考(red-hat):official tutorial of installing mongodb

# 1. 配置`mongo`的仓库信息
cat > /etc/yum.repos.d/mongodb-org-4.4.repo << EOF
[mongodb-org-4.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.4.asc
EOF

# 2. 通过`yum`安装
sudo yum install -y mongodb-org

# 3. 升级权限,比如
# sudo chown -R mongod:mongod <directory>
# 比如这是我之前的遗留mongo配置文件,需要升级权限,否则会出现`ExecStart=/usr/bin/mongod $OPTIONS (code=exited, status=14)`:  
# sudo chown mongod:mongod /tmp/mongodb-27017.sock

# 4. 启动
systemctl start mongod

修改mongodb配置

默认配置文件路径:/etc/mongod.conf

配置文件的具体信息参考:https://docs.mongodb.com/manual/reference/configuration-options/#security-options

修改其中的net.bindIp0.0.0.0(并重启)就可以给外网访问了(无需密码)。

About

基于electron、react、redux、webpack、typescript、express、mongodb的智能财务系统

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published