Browse Source

1225

master
lichong 3 months ago
parent
commit
c2910d752b
  1. 4
      electron-builder.yml
  2. 2
      package.json
  3. 2
      src/main/index.js
  4. 8
      src/renderer/src/App.vue
  5. BIN
      src/renderer/src/assets/excel/19年1月销售汇总.xls
  6. 2
      src/renderer/src/assets/js/db.js
  7. 7
      src/renderer/src/assets/json/sale.json
  8. 47
      src/renderer/src/components/tablecomponent.vue
  9. 371
      src/renderer/src/views/sale.vue

4
electron-builder.yml

@ -1,5 +1,5 @@
appId: com.electron.lichong
productName: 数据计算
productName: 销售统计
directories:
buildResources: build
files:
@ -14,7 +14,7 @@ win:
executableName: lichong-app
nsis:
oneClick: false
artifactName: 数据计算-${version}-setup.${ext}
artifactName: 销售统计-${version}-setup.${ext}
allowToChangeInstallationDirectory: true
shortcutName: ${productName}
uninstallDisplayName: ${productName}

2
package.json

@ -1,6 +1,6 @@
{
"name": "electron",
"version": "1.0.4",
"version": "1.0.0",
"description": "An Electron application with Vue",
"main": "./out/main/index.js",
"author": "lichong",

2
src/main/index.js

@ -23,7 +23,7 @@ function createWindow() {
})
mainWindow.on('ready-to-show', () => {
mainWindow.show()
// mainWindow.webContents.openDevTools()
mainWindow.webContents.openDevTools()
})
mainWindow.webContents.setWindowOpenHandler((details) => {
shell.openExternal(details.url)

8
src/renderer/src/App.vue

@ -1,6 +1,6 @@
<template>
<div class="appClass" v-if="isVip">
<shujucalComponent></shujucalComponent>
<saleComponent></saleComponent>
</div>
<div v-else class="noVip">
<h3>
@ -12,11 +12,10 @@
<script>
import _ from 'lodash'
import dayjs from 'dayjs'
import shujuduiComponent from "./views/shujudui.vue"
import shujucalComponent from "./views/shujucal.vue"
import saleComponent from "./views/sale.vue"
export default {
name: 'app',
components: { shujuduiComponent, shujucalComponent },
components: { saleComponent },
data() {
return {
_: _,
@ -24,7 +23,6 @@ export default {
isVip: false,
jihuoma: "",
zhucema: "",
tabName: "shujucal",
}
},
watch: {},

BIN
src/renderer/src/assets/excel/19年1月销售汇总.xls

Binary file not shown.

2
src/renderer/src/assets/js/db.js

@ -4,5 +4,5 @@ export const myDatabase = new Dexie('myDatabase');
// 定义数据库版本
myDatabase.version(2).stores({
sale: '++id, 货号, 品名, 供应商名称, 销售数量, 销售金额, 退货数量, 退货金额, 数量小计, 金额小计, &allInfo, create_at, update_at',
sale: '++id, 货号, tableName, 品名, 供应商名称, 销售数量, 销售金额, 退货数量, 退货金额, 数量小计, 金额小计, create_at, update_at',
});

7
src/renderer/src/assets/json/sale.json

@ -3,6 +3,7 @@
"label": "货号",
"prop": "货号",
"type": "text",
"width": "130",
"isSort": true,
"tableShow": true,
"formShow": true
@ -27,6 +28,7 @@
"label": "销售数量",
"prop": "销售数量",
"type": "text",
"width": "100",
"isSort": true,
"tableShow": true,
"formShow": true
@ -35,6 +37,7 @@
"label": "销售金额",
"prop": "销售金额",
"type": "text",
"width": "100",
"isSort": true,
"tableShow": true,
"formShow": true
@ -43,6 +46,7 @@
"label": "退货数量",
"prop": "退货数量",
"type": "text",
"width": "100",
"isSort": true,
"tableShow": true,
"formShow": true
@ -51,6 +55,7 @@
"label": "退货金额",
"prop": "退货金额",
"type": "text",
"width": "100",
"isSort": true,
"tableShow": true,
"formShow": true
@ -59,6 +64,7 @@
"label": "数量小计",
"prop": "数量小计",
"type": "text",
"width": "100",
"isSort": true,
"tableShow": true,
"formShow": true
@ -67,6 +73,7 @@
"label": "金额小计",
"prop": "金额小计",
"type": "text",
"width": "100",
"isSort": true,
"tableShow": true,
"formShow": true

47
src/renderer/src/components/tablecomponent.vue

@ -2,14 +2,14 @@
<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 }"
<vxe-table show-overflow :data="tableData" round :height="height" :scroll-y="{ enabled: true, gt: 0 }"
: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>
@checkbox-change="selectChange" ref="tableRef" border min-height="806px" :column-config="{ resizable: true }"
:footer-data="footerData" :show-footer="true">
<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">
v-for="(headerItem, headerIndex) in tableHeader" :key="headerIndex" :sortable="headerItem.isSort"
:width="headerItem.width">
<template #default="{ row }">
<template v-if="headerItem.type === 'text'">
<span>{{ row[headerItem.prop] }}</span>
@ -40,6 +40,10 @@
</template>
</vxe-column>
</vxe-table>
<vxe-pager :current-page.sync="pageVO.currentPage" :page-size.sync="pageVO.pageSize" :total="pageVO.total"
@page-change="pageChange" :page-sizes="pageVO.pageSizes"
:layouts="['Home', 'PrevJump', 'PrevPage', 'Number', 'NextPage', 'NextJump', 'End', 'Sizes', 'FullJump', 'Total']">
</vxe-pager>
</template>
</el-auto-resizer>
</div>
@ -51,7 +55,7 @@ import dayjs from 'dayjs'
export default {
name: 'tablecomponent',
components: {},
emits: ["selectChange", "edit", "info", "del"],
emits: ["selectChange", "edit", "info", "del", "pageChange"],
props: {
tableHeader: {
type: Array,
@ -59,6 +63,17 @@ export default {
return []
}
},
pageVO: {
type: Object,
default: () => {
return {
total: 0,
currentPage: 1,
pageSize: 16,
pageSizes: [16, 30, 50, 100]
}
}
},
tableData: {
type: Array,
default: () => {
@ -96,15 +111,31 @@ export default {
optClick(row, type) {
this.$emit(type, row)
},
pageChange({ pageSize, currentPage }) {
this.$emit("pageChange", { pageSize, currentPage })
},
},
async mounted() { },
watch: {},
computed: {}
computed: {
footerData() {
return [{
"货号": '合计',
"销售数量": _.sumBy(this.tableData, '销售数量').toFixed(2),
"销售金额": _.sumBy(this.tableData, '销售金额').toFixed(2),
"退货数量": _.sumBy(this.tableData, '退货数量').toFixed(2),
"退货金额": _.sumBy(this.tableData, '退货金额').toFixed(2),
"数量小计": _.sumBy(this.tableData, '数量小计').toFixed(2),
"金额小计": _.sumBy(this.tableData, '金额小计').toFixed(2),
}]
}
}
}
</script>
<style scoped>
.tableClass {
height: calc(100vh - 70px);
height: calc(100vh - 122px);
text-align: center;
text-align-last: center;
}

371
src/renderer/src/views/sale.vue

@ -2,7 +2,7 @@
<div class="rightClass">
<div>
<el-row style="margin-bottom: 8px;">
<el-col :span="16">
<el-col>
<el-button type="primary" @click="addData" size="large">
<el-icon>
<Plus />
@ -22,22 +22,38 @@
</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;left: 12px;margin-right: 24px;">
<el-button type="success" size="large">
<el-icon>
<Upload />
</el-icon>
<span>导入</span>
</el-button>
</el-upload>
<el-button type="primary" @click="openImport" size="large">
<el-icon>
<Delete />
</el-icon>
<span>导入数据</span>
</el-button>
<el-button type="primary" @click="exportData" size="large">
<el-icon>
<Delete />
</el-icon>
<span>导出</span>
</el-button>
<el-select v-model="searchObj.shopName" placeholder="请选择店铺名" class="selectClass" size="large">
<el-option v-for="item in shopOptions" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
<el-select v-model="searchObj.month" placeholder="请选择月份" class="selectClass" size="large">
<el-option v-for="item in monthOptions" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
<el-button type="primary" @click="updateSeach" size="large" style="margin-left: 16px;">
<el-icon>
<Delete />
</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">
@info="info" @del="del" @pageChange="pageChange" ref="tableComponentRef" :pageVO="pageVO">
</tablecomponent>
</div>
<el-dialog v-model="dialogFrom.visible" :title="dialogFrom.title" width="80%" :close-on-click-modal="false">
@ -51,6 +67,34 @@
</div>
</template>
</el-dialog>
<el-dialog v-model="importShow" title="导入数据" width="80%" :close-on-click-modal="false">
<div>
<el-select v-model="importObj.shopName" placeholder="请选择店铺名" class="selectClass" size="large">
<el-option v-for="item in shopOptions" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
<el-select v-model="importObj.month" placeholder="请选择月份" class="selectClass" size="large">
<el-option v-for="item in monthOptionsList" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
<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;left: 12px;margin-right: 24px;">
<el-button type="success" size="large">
<el-icon>
<Upload />
</el-icon>
<span>上传表格</span>
</el-button>
</el-upload>
</div>
<template #footer>
<div>
<el-button @click="cancelDialog">取消</el-button>
<el-button type="primary" @click="submitImport"> 确认 </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
@ -76,6 +120,7 @@ export default {
formHeader: [],
tableData: [],
selectionData: [],
importShow: false,
dialogFrom: {
visible: false,
title: "新增数据堆",
@ -83,12 +128,152 @@ export default {
formHeader: [],
formData: {}
},
sortObj: {},
fileData: [],
pageVO: {
total: 0,
currentPage: 1,
pageSize: 16,
pageSizes: [16, 30, 50, 100]
},
searchObj: {
shopName: "",
month: ""
},
importObj: {
shopName: "",
month: ""
},
shopOptions: [
{
label: "门店1(天猫小店泰和苑店)",
value: "1"
},
{
label: "门店2(天猫小店牡丹园店)",
value: "2"
},
{
label: "门店3(金叶便利东方红店)",
value: "3"
},
{
label: "门店4(天恩认养一头牛官旗店)",
value: "4"
}
],
monthOptions: [
{
label: "全部",
value: ""
},
{
label: "1月",
value: "1月"
},
{
label: "2月",
value: "2月"
},
{
label: "3月",
value: "3月"
},
{
label: "4月",
value: "4月"
},
{
label: "5月",
value: "5月"
},
{
label: "6月",
value: "6月"
},
{
label: "7月",
value: "7月"
},
{
label: "8月",
value: "8月"
},
{
label: "9月",
value: "9月"
},
{
label: "10月",
value: "10月"
},
{
label: "11月",
value: "11月"
},
{
label: "12月",
value: "12月"
},
],
monthOptionsList: [
{
label: "1月",
value: "1月"
},
{
label: "2月",
value: "2月"
},
{
label: "3月",
value: "3月"
},
{
label: "4月",
value: "4月"
},
{
label: "5月",
value: "5月"
},
{
label: "6月",
value: "6月"
},
{
label: "7月",
value: "7月"
},
{
label: "8月",
value: "8月"
},
{
label: "9月",
value: "9月"
},
{
label: "10月",
value: "10月"
},
{
label: "11月",
value: "11月"
},
{
label: "12月",
value: "12月"
},
],
tableName: "",
loading: false,
fileOriData: null,
}
},
methods: {
openImport() {
this.importShow = true
},
beforeAvatarUpload(rawFile) {
let imgList = ['text/csv', 'application/vnd.ms-excel', "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]
if (imgList.indexOf(rawFile.type) === -1) {
@ -106,50 +291,14 @@ export default {
let file = opts.file
this.fileDealData = []
let fileReader = new FileReader()
let dealDataObj = {
"销售数量": 1.2,
"销售金额": 1.2,
"数量小计": 1.2,
"金额小计": 1.2,
}
fileReader.onload = async function () {
fileReader.onload = async function (e) {
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])
console.log(132, sheetData);
let allList = []
let dealData = []
for (let i = 0; i < sheetData.length; i++) {
let element = sheetData[i];
let item = {}
for (let key in element) {
item[_.trim(key)] = _.trim(element[key])
}
if (item["行号"] && item["品名"] && item["供应商名称"]) {
for (let key in item) {
if (dealDataObj[_.trim(key)]) {
item[_.trim(key)] = (Number(_.trim(element[key])) * dealDataObj[_.trim(key)]).toFixed(2)
}
dealData.push(item[_.trim(key)])
}
item["allInfo"] = `${_.join(dealData, ",")}`
allList.push({
...item,
create_at: dayjs().format('YYYY-MM-DD HH:mm:ss'),
update_at: dayjs().format('YYYY-MM-DD HH:mm:ss')
})
}
}
try {
await myDatabase.sale.bulkAdd(allList)
} catch (error) {
ElMessage({
message: `销售数据重复,error:${error}`,
type: 'error',
})
}
await that.updateSeach()
that.fileData = _.cloneDeep(sheetData)
}
fileReader.onerror = function (error) {
ElMessage({
@ -162,23 +311,64 @@ export default {
//
async updateSeach() {
this.loading = true
let allSaleList = _.cloneDeep(await myDatabase.sale.toArray())
let dataTemp = []
dataTemp = _.cloneDeep(allSaleList)
let dataTempSort = dataTemp
if (_.get(this.sortObj, ["sort"], "")) {
//
dataTempSort = _.orderBy(dataTemp, [this.sortObj.prop], [_.get(this.sortObj, ["sort"], "") === 1 ? 'desc' : 'asc'])
let collection = myDatabase.sale
let shopNameTemp = _.trim(_.trim(this.searchObj.shopName))
let monthTemp = _.trim(_.trim(this.searchObj.month))
if (shopNameTemp) {
collection = collection.filter((equip) => equip.shopName === shopNameTemp)
}
if (monthTemp) {
collection = collection.filter((equip) => equip.month === monthTemp)
}
this.tableData = _.uniqBy(dataTempSort, "id")
this.pageVO.total = await collection.count()
this.tableData = await collection.offset((this.pageVO.currentPage - 1) * this.pageVO.pageSize).limit(this.pageVO.pageSize).toArray()
this.pageVO.pageSizes[5] = this.pageVO.total
this.loading = false
},
//
selectChange(selection) {
this.selectionData = _.cloneDeep(selection)
},
//
async exportData() {
let listCopy = _.cloneDeep(this.tableData)
if (listCopy.length) {
let allDataList = []
for (let i = 0; i < listCopy.length; i++) {
let listItem = listCopy[i];
let item = {}
for (let j = 0; j < this.tableHeader.length; j++) {
let headerItem = this.tableHeader[j];
item[headerItem.label] = listItem[headerItem.prop]
}
allDataList.push({ ...item })
}
let jsonWorkSheet = XLSX.utils.json_to_sheet(allDataList);
let workBook = {
SheetNames: ["sheet1"],
Sheets: {
["sheet1"]: jsonWorkSheet,
}
};
XLSX.writeFile(workBook, `销售表格${dayjs().format("YYYY-MM-DD_HH-mm-ss")}.xlsx`);
} else {
ElMessage({
type: 'error',
message: '当前表格无数据,请有数据后在导出',
})
}
},
//
async pageChange({ pageSize, currentPage }) {
this.pageVO.currentPage = currentPage
this.pageVO.pageSize = pageSize
console.log(186, this.pageVO);
await this.updateSeach()
},
//
cancelDialog() {
this.importShow = false
this.dialogFrom = {
visible: false,
title: "新增",
@ -187,6 +377,53 @@ export default {
formData: {}
}
},
//
async submitImport() {
let that = this
let dealDataObj = {
"销售数量": 1.2,
"销售金额": 1.2,
"退货数量": 1,
"退货金额": 1,
"数量小计": 1.2,
"金额小计": 1.2,
}
let allList = []
for (let i = 0; i < this.fileData.length; i++) {
let element = this.fileData[i];
let item = {}
for (let key in element) {
item[_.trim(key)] = _.trim(element[key])
}
if (item["行号"] && item["品名"] && item["供应商名称"]) {
for (let key in item) {
if (dealDataObj[_.trim(key)]) {
item[_.trim(key)] = Number((Number(_.trim(element[key])) * dealDataObj[_.trim(key)]).toFixed(2))
}
}
allList.push({
shopName: that.importObj.shopName,
month: that.importObj.month,
...item,
create_at: dayjs().format('YYYY-MM-DD HH:mm:ss'),
update_at: dayjs().format('YYYY-MM-DD HH:mm:ss')
})
}
}
try {
await myDatabase.sale.bulkAdd(allList)
this.cancelDialog()
await that.updateSeach()
} catch (error) {
ElMessage({
message: `销售数据重复,error:${error}`,
type: 'error',
})
}
await that.updateSeach()
},
//
async submitDialog() {
let params = { ...this.dialogFrom.formData, }
@ -228,7 +465,7 @@ export default {
edit(row) {
this.dialogFrom = {
visible: true,
title: `编辑${row.name}`,
title: `编辑${row['货号']}`,
type: "put",
disabled: false,
formHeader: this.formHeader,
@ -239,7 +476,7 @@ export default {
info(row) {
this.dialogFrom = {
visible: true,
title: `查看${row.name}`,
title: `查看${row['货号']}`,
type: "info",
disabled: true,
formHeader: this.formHeader,
@ -256,7 +493,7 @@ export default {
let idList = []
for (let i = 0; i < delList.length; i++) {
let element = delList[i];
tooltipList.push(element.name)
tooltipList.push(element["货号"])
idList.push(element.id)
}
ElMessageBox.confirm(
@ -333,4 +570,10 @@ export default {
width: 200px;
position: relative;
}
.selectClass {
display: inline-block;
max-width: 200px;
margin-left: 16px;
}
</style>

Loading…
Cancel
Save