Skip to content

Commit e32ac0e

Browse files
author
xiaotian
committed
init
0 parents  commit e32ac0e

18 files changed

+624
-0
lines changed

.editorconfig

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# http://editorconfig.org
2+
root = true
3+
4+
[*]
5+
indent_style = space
6+
indent_size = 2
7+
end_of_line = lf
8+
charset = utf-8
9+
trim_trailing_whitespace = true
10+
insert_final_newline = true
11+
12+
[*.md]
13+
trim_trailing_whitespace = false
14+
15+
[Makefile]
16+
indent_style = tab

.gitignore

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/npm-debug.log*
6+
/yarn-error.log
7+
/yarn.lock
8+
/package-lock.json
9+
10+
# production
11+
/dist
12+
13+
# misc
14+
.DS_Store
15+
16+
# umi
17+
/src/.umi
18+
/src/.umi-production
19+
/src/.umi-test
20+
/.env.local

.prettierignore

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
**/*.md
2+
**/*.svg
3+
**/*.ejs
4+
**/*.html
5+
package.json
6+
.umi
7+
.umi-production
8+
.umi-test

.prettierrc

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"singleQuote": true,
3+
"trailingComma": "all",
4+
"printWidth": 80,
5+
"overrides": [
6+
{
7+
"files": ".prettierrc",
8+
"options": { "parser": "json" }
9+
}
10+
]
11+
}

.umirc.ts

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { defineConfig } from 'umi';
2+
import WindiCSSWebpackPlugin from 'windicss-webpack-plugin'
3+
4+
export default defineConfig({
5+
outputPath: 'app/build',
6+
nodeModulesTransform: {
7+
type: 'none',
8+
},
9+
routes: [
10+
{ path: '/', component: '@/pages/index' },
11+
],
12+
fastRefresh: {},
13+
chainWebpack(memo, { env, webpack, createCSSRule }) {
14+
memo.plugin('windicss').use(WindiCSSWebpackPlugin)
15+
}
16+
});

README.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# 库存管理系统(供学习electron)
2+
3+
## 技术栈
4+
umijs + electron
5+
6+
## 开发环境启动
7+
```
8+
yarn start:app
9+
```
10+
## 截图
11+
![](./imgs/[email protected])
12+
![](./imgs/[email protected])

app/main.ts

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
const { app, BrowserWindow, ipcMain, dialog } = require('electron')
2+
const path = require('path')
3+
const fs = require('fs')
4+
5+
const isPro = process.env.NODE_ENV !== "development";
6+
function renderWindow() {
7+
const mainWindow = new BrowserWindow({
8+
width: 750,
9+
height: 550,
10+
webPreferences: {
11+
nodeIntegration: true,
12+
contextIsolation: false
13+
// preload: path.resolve(__dirname, 'preload.js')
14+
}
15+
})
16+
17+
if (isPro) {
18+
mainWindow.loadFile(`${__dirname}/build/index.html`);
19+
} else {
20+
mainWindow.loadURL('http://localhost:8000/');
21+
// 打开开发者工具,默认不打开
22+
mainWindow.webContents.openDevTools()
23+
}
24+
25+
ipcMain.on('read-laihuo-excel', async (evt) => {
26+
const {filePaths} = await dialog.showOpenDialog({
27+
filters: [{
28+
name: 'Excel',
29+
extensions: ['xlsx']
30+
}]
31+
})
32+
evt.reply('read-laihuo-success', filePaths[0], fs.readFileSync(filePaths[0]))
33+
})
34+
ipcMain.on('read-fahuo-excel', async (evt) => {
35+
const {filePaths} = await dialog.showOpenDialog({
36+
filters: [{
37+
name: 'Excel',
38+
extensions: ['xlsx']
39+
}]
40+
})
41+
evt.reply('read-fahuo-success', filePaths[0], fs.readFileSync(filePaths[0]))
42+
})
43+
}
44+
45+
app.whenReady().then(() => {
46+
renderWindow()
47+
app.on('activate', function () {
48+
if (BrowserWindow.getAllWindows().length === 0) renderWindow()
49+
})
50+
})
51+
52+
app.on('window-all-closed', () => {
53+
if (process.platform === 'darwin') return
54+
55+
app.quit()
56+
})

imgs/[email protected]

111 KB
Loading

imgs/[email protected]

108 KB
Loading

mock/.gitkeep

Whitespace-only changes.

package.json

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"private": true,
3+
"scripts": {
4+
"start:app": "concurrently \"cross-env BROWSER=none yarn start\" \"wait-on http://localhost:8000 && cross-env NODE_ENV=development electron app/main.ts\"",
5+
"start": "umi dev",
6+
"build": "umi build",
7+
"postinstall": "umi generate tmp",
8+
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
9+
"test": "umi-test",
10+
"test:coverage": "umi-test --coverage"
11+
},
12+
"gitHooks": {
13+
"pre-commit": "lint-staged"
14+
},
15+
"lint-staged": {
16+
"*.{js,jsx,less,md,json}": [
17+
"prettier --write"
18+
],
19+
"*.ts?(x)": [
20+
"prettier --parser=typescript --write"
21+
]
22+
},
23+
"dependencies": {
24+
"@ant-design/pro-layout": "^6.5.0",
25+
"exceljs": "^4.3.0",
26+
"react": "17.x",
27+
"react-dom": "17.x",
28+
"umi": "^3.5.20"
29+
},
30+
"devDependencies": {
31+
"@types/react": "^17.0.0",
32+
"@types/react-dom": "^17.0.0",
33+
"@umijs/preset-react": "1.x",
34+
"@umijs/test": "^3.5.20",
35+
"concurrently": "^6.4.0",
36+
"cross-env": "^7.0.3",
37+
"electron": "^16.0.1",
38+
"lint-staged": "^10.0.7",
39+
"prettier": "^2.2.0",
40+
"typescript": "^4.1.2",
41+
"wait-on": "^6.0.0",
42+
"windicss-webpack-plugin": "^1.5.8",
43+
"yorkie": "^2.0.0"
44+
}
45+
}

src/app.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import 'windi.css'

src/component/data-preview/index.tsx

+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
import { Button, Table } from 'antd'
2+
import Excel from 'exceljs'
3+
import { useState, useEffect } from 'react'
4+
const { ipcRenderer } = window.require('electron')
5+
6+
type DataPreviewProps = {
7+
laihuoFile: ArrayBuffer
8+
fahuoFile: ArrayBuffer
9+
colorMap: Record<string, string>
10+
reupload: () => void
11+
}
12+
export default (props: DataPreviewProps) => {
13+
const [loading, setLoading] = useState(false)
14+
const [kucunWb, setKucunWb] = useState<Excel.Workbook>()
15+
// 要预览的数据
16+
const [dataList, setDataList] = useState<any[]>([])
17+
async function initData() {
18+
const jinhuoWorkbook = await new Excel.Workbook().xlsx.load(props.laihuoFile)
19+
20+
const addressRE = /^([A-Z]+)(\d+)$/
21+
const emptySymbolRE = /\s/g
22+
const colorNumRE = /[A-Z\d\s#-]+/
23+
const jinhuoMap = {}
24+
const colorMap = props.colorMap
25+
jinhuoWorkbook.eachSheet((sheet) => {
26+
const row1 = sheet.getRow(1)
27+
const sheetName = sheet.name.replace(emptySymbolRE, '')
28+
sheet.eachRow((row, rowNum) => {
29+
if (rowNum <= 1) return
30+
31+
row.eachCell((cell, cellNum) => {
32+
if (cellNum <= 1) return
33+
34+
// @ts-ignore
35+
const colorCN = row.getCell(1).value.replace(colorNumRE, '').replace(emptySymbolRE, '')
36+
// @ts-ignore
37+
const colKey = addressRE.exec(cell.address)[1]
38+
const size = row1.getCell(colKey).value
39+
// @ts-ignore
40+
const key = `${sheetName}-${colorMap[colorCN]}-${size.replace(emptySymbolRE, '')}`
41+
// @ts-ignore
42+
const val = jinhuoMap[key]
43+
if (val && val >= 0) {
44+
// @ts-ignore
45+
jinhuoMap[key] += cell.value
46+
} else {
47+
// @ts-ignore
48+
jinhuoMap[key] = cell.value
49+
}
50+
})
51+
})
52+
})
53+
54+
const dataList: any[] = []
55+
// @ts-ignore
56+
function createKucunWb(jinhuoMap) {
57+
const kucunWorkbook = new Excel.Workbook()
58+
kucunWorkbook.properties.date1904 = true
59+
const sheet = kucunWorkbook.addWorksheet('库存')
60+
sheet.columns = [
61+
{ header: '卖家SKU', key: 'sku', width: 20 },
62+
{ header: 'ASIN', key: 'asin', width: 20 },
63+
{ header: '进货总数', key: 'jinhuoNum', width: 20 },
64+
{ header: '发货总数', key: 'fahuoNum', width: 20 },
65+
{ header: '仓库剩余', key: 'remain', width: 20 },
66+
]
67+
68+
const skuMap = {}
69+
Object.keys(jinhuoMap).forEach((key, index) => {
70+
// @ts-ignore
71+
skuMap[key] = index + 2
72+
const row = {
73+
sku: key,
74+
jinhuoNum: jinhuoMap[key],
75+
fahuoNum: 0,
76+
remain: jinhuoMap[key]
77+
}
78+
dataList.push(row)
79+
sheet.addRow(row)
80+
})
81+
82+
return [kucunWorkbook, skuMap]
83+
}
84+
// 读取出货表计算库存并输出到库存表
85+
const [kucunWorkbook, skuMap] = createKucunWb(jinhuoMap)
86+
// @ts-ignore
87+
const kucunSheet = kucunWorkbook.getWorksheet('库存')
88+
const fahuoWorkbook = await new Excel.Workbook().xlsx.load(props.fahuoFile)
89+
fahuoWorkbook.eachSheet(sheet => {
90+
sheet.eachRow((row, rowNum) => {
91+
if (rowNum <= 1) return
92+
93+
let sku = row.getCell(1).value
94+
// @ts-ignore
95+
sku = sku.split('-').slice(0, 3).join('-')
96+
// @ts-ignore
97+
const index = skuMap[sku]
98+
const data = dataList[index - 2]
99+
const kucunRow = kucunSheet.getRow(index)
100+
const asin = row.getCell('B').value
101+
kucunRow.getCell('B').value = asin
102+
data.asin = asin
103+
104+
// 累加发货数
105+
let fahuoNum = kucunRow.getCell('D').value
106+
kucunRow.getCell('D').value = fahuoNum = fahuoNum + row.getCell('C').value
107+
data.fahuoNum = fahuoNum
108+
109+
// 计算库存数
110+
const remain = kucunRow.getCell('remain').value - fahuoNum
111+
kucunRow.getCell('E').value = remain
112+
data.remain = remain
113+
})
114+
})
115+
// @ts-ignore
116+
setKucunWb(kucunWorkbook)
117+
setDataList(dataList)
118+
}
119+
120+
useEffect(() => {
121+
setLoading(true)
122+
initData().then(() => setLoading(false)).catch(() => setLoading(false))
123+
}, [])
124+
125+
async function handleExport() {
126+
const buffer = await kucunWb?.xlsx.writeBuffer()
127+
const a = document.createElement('a')
128+
a.download = '库存.xlsx'
129+
a.href = URL.createObjectURL(new Blob([buffer!]))
130+
document.body.appendChild(a)
131+
a.click()
132+
document.body.removeChild(a)
133+
ipcRenderer.send('export-res', kucunWb)
134+
}
135+
136+
return (
137+
<div className="w-full px-20 py-4 text-right">
138+
<Table rowKey="sku" loading={loading} scroll={{y: 300}} dataSource={dataList} pagination={false} columns={[{
139+
title: '卖家SKU',
140+
dataIndex: 'sku'
141+
}, {
142+
title: 'ASIN',
143+
dataIndex: 'asin'
144+
}, {
145+
title: '进货总数',
146+
dataIndex: 'jinhuoNum'
147+
}, {
148+
title: '发货总数',
149+
dataIndex: 'fahuoNum'
150+
}, {
151+
title: '仓库剩余',
152+
dataIndex: 'remain'
153+
}]}
154+
></Table>
155+
<Button disabled={loading} className="mt-4" onClick={props.reupload}>重新上传</Button>
156+
<Button disabled={loading} className="mt-4 ml-4" type="primary" onClick={handleExport}>导出excel</Button>
157+
</div>
158+
)
159+
}

0 commit comments

Comments
 (0)