fix -库房统计
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/backend/target/
|
||||
/backend/.idea/
|
||||
/frontend/node_modules
|
||||
@@ -9,11 +9,7 @@ import cc.mrbird.febs.cos.service.IStockPutService;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@@ -100,5 +96,16 @@ public class StockInfoController {
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据月份获取药品统计情况
|
||||
*
|
||||
* @param date 日期
|
||||
* @return 结果
|
||||
*/
|
||||
@GetMapping("/selectStatisticsByMonth")
|
||||
public R selectStatisticsByMonth(@RequestParam("date") String date) throws FebsException {
|
||||
return R.ok(stockInfoService.selectStatisticsByMonth(date));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package cc.mrbird.febs.cos.dao;
|
||||
|
||||
import cc.mrbird.febs.cos.entity.GoodsBelong;
|
||||
import cc.mrbird.febs.cos.entity.StockInfo;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
@@ -37,4 +38,13 @@ public interface StockInfoMapper extends BaseMapper<StockInfo> {
|
||||
|
||||
// 本月数据统计
|
||||
LinkedHashMap<String, Object> stockInfoByMonth();
|
||||
|
||||
/**
|
||||
* 根据时间获取订单信息
|
||||
*
|
||||
* @param year 年度
|
||||
* @param month 月度
|
||||
* @return 结果
|
||||
*/
|
||||
List<GoodsBelong> selectOrderByCheckMonth(@Param("year") Integer year, @Param("month") Integer month);
|
||||
}
|
||||
|
||||
@@ -96,4 +96,9 @@ public class ArchivesInfo implements Serializable {
|
||||
private String delFlag;
|
||||
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* 提交材料
|
||||
*/
|
||||
private String material;
|
||||
}
|
||||
|
||||
@@ -33,4 +33,12 @@ public interface IStockInfoService extends IService<StockInfo> {
|
||||
LinkedHashMap<String, Object> home(Integer type, Integer userId);
|
||||
|
||||
boolean checkStock(List<GoodsBelong> goodsBelongList);
|
||||
|
||||
/**
|
||||
* 根据月份获取药品统计情况
|
||||
*
|
||||
* @param date 日期
|
||||
* @return 结果
|
||||
*/
|
||||
LinkedHashMap<String, Object> selectStatisticsByMonth(String date) throws FebsException;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import cc.mrbird.febs.cos.entity.StockPut;
|
||||
import cc.mrbird.febs.cos.service.*;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
@@ -22,9 +23,8 @@ import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author FanK
|
||||
@@ -165,4 +165,76 @@ public class StockInfoServiceImpl extends ServiceImpl<StockInfoMapper, StockInfo
|
||||
result.put("stockInfo", baseMapper.stockInfoByMonth());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据月份获取药品统计情况
|
||||
*
|
||||
* @param date 日期
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public LinkedHashMap<String, Object> selectStatisticsByMonth(String date) throws FebsException {
|
||||
if (StrUtil.isEmpty(date)) {
|
||||
throw new FebsException("参数不能为空");
|
||||
}
|
||||
|
||||
int year = DateUtil.year(DateUtil.parseDate(date));
|
||||
int month = DateUtil.month(DateUtil.parseDate(date)) + 1;
|
||||
|
||||
// 返回数据
|
||||
LinkedHashMap<String, Object> result = new LinkedHashMap<String, Object>() {
|
||||
{
|
||||
put("num", Collections.emptyList());
|
||||
put("price", Collections.emptyList());
|
||||
}
|
||||
};
|
||||
|
||||
// 获取订单详情
|
||||
List<GoodsBelong> orderList = baseMapper.selectOrderByCheckMonth(year, month);
|
||||
if (CollectionUtil.isEmpty(orderList)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
List<GoodsBelong> putOrderList = new ArrayList<>();
|
||||
List<GoodsBelong> outOrderList = new ArrayList<>();
|
||||
|
||||
for (GoodsBelong goodsBelong : orderList) {
|
||||
if (goodsBelong.getNum().contains("PUT-")) {
|
||||
putOrderList.add(goodsBelong);
|
||||
}
|
||||
if (goodsBelong.getNum().contains("OUT-")) {
|
||||
outOrderList.add(goodsBelong);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, List<GoodsBelong>> putOrderMap = putOrderList.stream().collect(Collectors.groupingBy(GoodsBelong::getName));
|
||||
Map<String, List<GoodsBelong>> outOrderMap = outOrderList.stream().collect(Collectors.groupingBy(GoodsBelong::getName));
|
||||
|
||||
List<Map<String, Object>> putNumMap = new ArrayList<>();
|
||||
List<Map<String, Object>> outNumMap = new ArrayList<>();
|
||||
|
||||
putOrderMap.forEach((key, value) -> {
|
||||
Map<String, Object> numItem = new HashMap<String, Object>() {
|
||||
{
|
||||
put("name", key);
|
||||
put("value", value.stream().map(GoodsBelong::getAmount).reduce(Integer::sum));
|
||||
}
|
||||
};
|
||||
putNumMap.add(numItem);
|
||||
});
|
||||
|
||||
outOrderMap.forEach((key, value) -> {
|
||||
Map<String, Object> numItem = new HashMap<String, Object>() {
|
||||
{
|
||||
put("name", key);
|
||||
put("value", value.stream().map(GoodsBelong::getAmount).reduce(Integer::sum));
|
||||
}
|
||||
};
|
||||
outNumMap.add(numItem);
|
||||
});
|
||||
|
||||
result.put("putNumMap", putNumMap);
|
||||
result.put("outNumMap", outNumMap);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
mail,
|
||||
phone,
|
||||
create_date,
|
||||
del_flag
|
||||
del_flag,
|
||||
material
|
||||
from
|
||||
archives_info
|
||||
where
|
||||
|
||||
@@ -192,4 +192,15 @@
|
||||
( SELECT count( 1 ) AS outCount FROM stock_info si WHERE si.is_in = 2 ) AS on2,
|
||||
( SELECT IFNULL( SUM( si.amount * si.price ),0) AS price FROM stock_info si WHERE si.is_in = 1 ) AS on3
|
||||
</select>
|
||||
|
||||
<!-- 根据时间获取订单信息 -->
|
||||
<select id="selectOrderByCheckMonth" resultType="cc.mrbird.febs.cos.entity.GoodsBelong">
|
||||
select
|
||||
oi.*
|
||||
from
|
||||
goods_belong oi
|
||||
where
|
||||
DATE_FORMAT( oi.create_date, '%Y' ) = #{year}
|
||||
and DATE_FORMAT( oi.create_date, '%m' ) = #{month}
|
||||
</select>
|
||||
</mapper>
|
||||
|
||||
@@ -111,6 +111,28 @@
|
||||
]"/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label='材料文件' v-bind="formItemLayout">
|
||||
<a-upload
|
||||
name="avatar"
|
||||
action="http://127.0.0.1:9527/file/fileUpload/"
|
||||
list-type="picture-card"
|
||||
:file-list="fileList"
|
||||
@preview="handlePreview"
|
||||
@change="picHandleChange"
|
||||
>
|
||||
<div v-if="fileList.length < 8">
|
||||
<a-icon type="plus" />
|
||||
<div class="ant-upload-text">
|
||||
Upload
|
||||
</div>
|
||||
</div>
|
||||
</a-upload>
|
||||
<a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
|
||||
<img alt="example" style="width: 100%" :src="previewImage" />
|
||||
</a-modal>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-button @click="handleSubmit" type="primary">修改</a-button>
|
||||
</a-form>
|
||||
@@ -140,6 +162,14 @@ import HeadInfo from '@/views/common/HeadInfo'
|
||||
import {mapState} from 'vuex'
|
||||
import moment from 'moment'
|
||||
moment.locale('zh-cn')
|
||||
function getBase64 (file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader()
|
||||
reader.readAsDataURL(file)
|
||||
reader.onload = () => resolve(reader.result)
|
||||
reader.onerror = error => reject(error)
|
||||
})
|
||||
}
|
||||
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 24 },
|
||||
@@ -150,6 +180,9 @@ export default {
|
||||
components: {HeadInfo},
|
||||
data () {
|
||||
return {
|
||||
fileList: [],
|
||||
previewVisible: false,
|
||||
previewImage: '',
|
||||
form: this.$form.createForm(this),
|
||||
formItemLayout,
|
||||
series6: [{
|
||||
@@ -378,6 +411,28 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleCancel () {
|
||||
this.previewVisible = false
|
||||
},
|
||||
async handlePreview (file) {
|
||||
if (!file.url && !file.preview) {
|
||||
file.preview = await getBase64(file.originFileObj)
|
||||
}
|
||||
this.previewImage = file.url || file.preview
|
||||
this.previewVisible = true
|
||||
},
|
||||
picHandleChange ({ fileList }) {
|
||||
this.fileList = fileList
|
||||
},
|
||||
imagesInit (images) {
|
||||
if (images !== null && images !== '') {
|
||||
let imageList = []
|
||||
images.split(',').forEach((image, index) => {
|
||||
imageList.push({uid: index, name: image, status: 'done', url: 'http://127.0.0.1:9527/imagesWeb/' + image})
|
||||
})
|
||||
this.fileList = imageList
|
||||
}
|
||||
},
|
||||
welcome () {
|
||||
const date = new Date()
|
||||
const hour = date.getHours()
|
||||
@@ -389,6 +444,10 @@ export default {
|
||||
let fields = ['name', 'content', 'team']
|
||||
let obj = {}
|
||||
Object.keys(combo).forEach((key) => {
|
||||
if (key === 'material') {
|
||||
this.fileList = []
|
||||
this.imagesInit(combo['material'])
|
||||
}
|
||||
if (fields.indexOf(key) !== -1) {
|
||||
this.form.getFieldDecorator(key)
|
||||
obj[key] = combo[key]
|
||||
@@ -397,8 +456,17 @@ export default {
|
||||
this.form.setFieldsValue(obj)
|
||||
},
|
||||
handleSubmit () {
|
||||
let images = []
|
||||
this.fileList.forEach(image => {
|
||||
if (image.response !== undefined) {
|
||||
images.push(image.response)
|
||||
} else {
|
||||
images.push(image.name)
|
||||
}
|
||||
})
|
||||
this.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
values.material = images.length > 0 ? images.join(',') : null
|
||||
values.id = this.studentInfo.id
|
||||
this.$put('/cos/archives-info', {
|
||||
...values
|
||||
|
||||
165
frontend/src/views/admin/statistics/Statistics.vue
Normal file
165
frontend/src/views/admin/statistics/Statistics.vue
Normal file
@@ -0,0 +1,165 @@
|
||||
<template>
|
||||
<a-card :bordered="false" class="card-area">
|
||||
<div style="background:#ECECEC; padding:30px;margin-top: 30px;margin-bottom: 30px">
|
||||
<a-row :gutter="30">
|
||||
<a-col :span="6" :key="index">
|
||||
<a-month-picker @change="onChange" style="width: 100%" placeholder="选择时间" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
<a-row :gutter="20">
|
||||
<a-col :span="12">
|
||||
<a-card hoverable :bordered="false" style="width: 100%">
|
||||
<a-skeleton active v-if="loading" />
|
||||
<apexchart v-if="!loading" type="bar" height="300" :options="chartOptions1" :series="series1"></apexchart>
|
||||
</a-card>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-card hoverable :bordered="false" style="width: 100%">
|
||||
<a-skeleton active v-if="loading" />
|
||||
<apexchart v-if="!loading" type="bar" height="300" :options="chartOptions2" :series="series2"></apexchart>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment'
|
||||
|
||||
export default {
|
||||
name: 'Work',
|
||||
data () {
|
||||
return {
|
||||
workStatusList: [],
|
||||
loading: false,
|
||||
series1: [],
|
||||
chartOptions1: {
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: 300
|
||||
},
|
||||
title: {
|
||||
text: '入库统计',
|
||||
align: 'left'
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false,
|
||||
columnWidth: '55%'
|
||||
}
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
stroke: {
|
||||
show: true,
|
||||
width: 2,
|
||||
colors: ['transparent']
|
||||
},
|
||||
xaxis: {
|
||||
categories: []
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: ''
|
||||
}
|
||||
},
|
||||
fill: {
|
||||
opacity: 1
|
||||
},
|
||||
tooltip: {
|
||||
y: {
|
||||
formatter: function (val) {
|
||||
return val + ' 单'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
series2: [],
|
||||
chartOptions2: {
|
||||
chart: {
|
||||
type: 'bar',
|
||||
height: 300
|
||||
},
|
||||
title: {
|
||||
text: '出库统计',
|
||||
align: 'left'
|
||||
},
|
||||
plotOptions: {
|
||||
bar: {
|
||||
horizontal: false,
|
||||
columnWidth: '55%'
|
||||
}
|
||||
},
|
||||
dataLabels: {
|
||||
enabled: false
|
||||
},
|
||||
stroke: {
|
||||
show: true,
|
||||
width: 2,
|
||||
colors: ['transparent']
|
||||
},
|
||||
xaxis: {
|
||||
categories: []
|
||||
},
|
||||
yaxis: {
|
||||
title: {
|
||||
text: ''
|
||||
}
|
||||
},
|
||||
fill: {
|
||||
opacity: 1
|
||||
},
|
||||
tooltip: {
|
||||
y: {
|
||||
formatter: function (val) {
|
||||
return val + ' 元'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.selectOrderDays(moment(new Date()).format('YYYY-MM'))
|
||||
},
|
||||
methods: {
|
||||
onChange (date, dateString) {
|
||||
this.selectOrderDays(dateString)
|
||||
},
|
||||
selectOrderDays (date) {
|
||||
date = date + '-01'
|
||||
this.loading = true
|
||||
this.$get(`/cos/stock-info/selectStatisticsByMonth`, {
|
||||
date
|
||||
}).then((r) => {
|
||||
this.series1 = []
|
||||
this.series2 = []
|
||||
console.log(r.data)
|
||||
if (r.data.putNumMap && r.data.putNumMap.length !== 0) {
|
||||
this.chartOptions1.xaxis.categories = Array.from(r.data.putNumMap, ({name}) => name)
|
||||
r.data.putNumMap.forEach(e => {
|
||||
let value = { name: e.name, data: [e.value] }
|
||||
this.series1.push(value)
|
||||
})
|
||||
}
|
||||
if (r.data.outNumMap && r.data.outNumMap.length !== 0) {
|
||||
this.chartOptions2.xaxis.categories = Array.from(r.data.outNumMap, ({name}) => name)
|
||||
r.data.outNumMap.forEach(e => {
|
||||
let value = { name: e.name, data: [e.value] }
|
||||
this.series2.push(value)
|
||||
})
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.loading = false
|
||||
}, 200)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -231,6 +231,18 @@ export default {
|
||||
return '- -'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
title: '材料文件',
|
||||
dataIndex: 'material',
|
||||
customRender: (text, record, index) => {
|
||||
if (!record.material) return <a-avatar shape="square" icon="user" />
|
||||
return <a-popover>
|
||||
<template slot="content">
|
||||
<a-avatar shape="square" size={132} icon="user" src={ 'http://127.0.0.1:9527/imagesWeb/' + record.material.split(',')[0] } />
|
||||
</template>
|
||||
<a-avatar shape="square" icon="user" src={ 'http://127.0.0.1:9527/imagesWeb/' + record.material.split(',')[0] } />
|
||||
</a-popover>
|
||||
}
|
||||
}, {
|
||||
title: '创建时间',
|
||||
dataIndex: 'createDate',
|
||||
|
||||
Reference in New Issue
Block a user