作者 朱兆平

Merge branch 'master_dev'

... ... @@ -14,7 +14,7 @@
"@xkeshi/vue-barcode": "^1.0.0",
"axios": "^0.19.0",
"common": "^0.2.5",
"echarts": "^5.0.1",
"echarts": "^4.9.0",
"echarts-liquidfill": "^3.0.0",
"element-ui": "^2.13.2",
"eslint": "^5.14.1",
... ...
... ... @@ -14,6 +14,7 @@ export const addTrans = params => { return http.post(`${baseUrl}/addTrans`, par
export const ediTrans = params => { return http.post(`${baseUrl}/ediTrans`, params); };
export const send = params => { return http.post(`${baseUrl}/send`, params); };
export const role = params => { return http.get(`${baseUrl1}/getPermission`, params); };
export const analysisAPI = params => { return http.post(`${baseUrl}/totalAnalysis`, params); };
... ...
... ... @@ -69,7 +69,7 @@ import WaybillQuerys from './views/nmms_fast/WaybillQuerys.vue'
import echarts from './views/charts/echarts.vue'
import echarts from './views/charts/dataEcharts.vue'
import earthCharts from './views/charts/earthCharts.vue'
import SecrityInspection from './views/staff/security_inspection.vue'
... ... @@ -104,6 +104,7 @@ import queryConfirmatory from './views/airtransport/queryConfirmatory.vue'
import configure from './views/airtransport/configure.vue'
import queryConfigure from './views/airtransport/queryConfigure.vue'
import transit from './views/transit/transit.vue'
import transitCharts from './views/transit/transitCharts.vue'
import technological from './views/technological/technological.vue'
import example from './views/technological/example.vue'
import task from './views/technological/task.vue'
... ... @@ -532,6 +533,7 @@ let routes = [
iconCls: 'el-icon-delete-location',
children: [
{path:'/transit',component:transit,name:'转关运抵申报'},
{path:'/transitCharts',component:transitCharts,name:'转关运抵统计'}
]
},
{
... ...
... ... @@ -47,9 +47,10 @@
<el-table-column
fixed="right"
label="操作"
width="120">
width="220">
<template slot-scope="scope">
<el-button type="danger" size="mini" @click="applyEnd(scope.row)">结束出勤</el-button>
<el-button type="success" @click="centerDialogVisible = true">图片上传</el-button>
</template>
</el-table-column>
</el-table>
... ... @@ -65,6 +66,31 @@
:total="total">
</el-pagination>
</el-row>
<el-dialog
title="提示"
:visible.sync="centerDialogVisible"
width="30%"
center>
<div>
<el-upload
class="avatar-uploader"
action="https://jsonplaceholder.typicode.com/posts/"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload">
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
<el-input v-model="description" placeholder="请输入图片描述"></el-input>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="centerDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="centerDialogVisible = false">确 定</el-button>
</span>
</el-dialog>
</el-card>
</el-row>
</template>
... ... @@ -75,68 +101,114 @@
export default {
data() {
return {
centerDialogVisible: false,
queryInfo: {
lisenceNo:'',
lisenceNo: '',
// 当前页数
pageNum: 1,
// 每页几条数据
pageSize: 10,
},
total: 0,
tableData:[],
tableData: [],
formInline: {
user: '',
},
imageUrl: '',
description:''
}
},
methods: {
handleSizeChange(val) {
this.queryInfo.pageSize = val
this.getList()
handleAvatarSuccess(res, file) {
this.imageUrl = URL.createObjectURL(file.raw);
},
handleCurrentChange(val) {
this.queryInfo.pageNum = val
this.getList()
},
getList() {
const _this = this
selectList(this.queryInfo).then((response) => {
const res = response.data
console.log(response.data)
if (res.code !== '200') {
return _this.$message.error('获取消息收发记录,失败!')
}
// 获取列表数据
_this.tableData = res.data.list;
// 获取列表的总记录数
_this.total = res.data.total
_this.$message.success('获取消息收发记录,成功!')
}).catch(error => {
// 关闭加载
_this.$message.error(error.toString())
})
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!');
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!');
}
return isJPG && isLt2M;
},
// 结束出勤
applyEnd(row) {
// 弹框询问是否结束?
this.$confirm('是否继续?', '警告', {
confirmButtonText: '确定结束',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
DoneTask(row).then((response) => {
handleSizeChange(val) {
this.queryInfo.pageSize = val
this.getList()
},
handleCurrentChange(val) {
this.queryInfo.pageNum = val
this.getList()
},
getList() {
const _this = this
selectList(this.queryInfo).then((response) => {
const res = response.data
this.$message.success(res.msg)
this.getList()
console.log(response.data)
if (res.code !== '200') {
return _this.$message.error('获取消息收发记录,失败!')
}
// 获取列表数据
_this.tableData = res.data.list;
// 获取列表的总记录数
_this.total = res.data.total
_this.$message.success('获取消息收发记录,成功!')
}).catch(error => {
this.$message.error(error)
// 关闭加载
_this.$message.error(error.toString())
})
}).catch(() => {
})
},
// 结束出勤
applyEnd(row) {
// 弹框询问是否结束?
this.$confirm('是否继续?', '警告', {
confirmButtonText: '确定结束',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
DoneTask(row).then((response) => {
const res = response.data
this.$message.success(res.msg)
this.getList()
}).catch(error => {
this.$message.error(error)
})
}).catch(() => {
})
},
},
},
mounted() {
this.getList();
}
}
</script>
<style>
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>
... ...
<template>
<section class="todoapp">
<!-- header -->
<header class="header">
<input class="new-todo" autocomplete="off" placeholder="今日申报" @keyup.enter="addTodo">
</header>
<!-- main section -->
<section v-show="todos.length" class="main">
<input id="toggle-all" :checked="allChecked" class="toggle-all" type="checkbox" @change="toggleAll({ done: !allChecked })">
<label for="toggle-all" />
<ul class="todo-list">
<todo
v-for="(todo, index) in filteredTodos"
:key="index"
:todo="todo"
@toggleTodo="toggleTodo"
@editTodo="editTodo"
@deleteTodo="deleteTodo"
/>
</ul>
</section>
<!-- footer -->
<footer v-show="todos.length" class="footer">
<span class="todo-count">
<strong>{{ remaining }}</strong>
{{ remaining | pluralize('个转关运抵申请') }} 未申报
</span>
<ul class="filters">
<li v-for="(val, key) in filters" :key="key">
<a :class="{ selected: visibility === key }" @click.prevent="visibility = key">{{ key | capitalize }}</a>
</li>
</ul>
<!-- <button class="clear-completed" v-show="todos.length > remaining" @click="clearCompleted">
Clear completed
</button> -->
</footer>
</section>
</template>
<script>
import Todo from '@/views/dashboard/components/TodoList/Todo.vue'
import {selectTrans} from "@/api/trn";
const STORAGE_KEY = 'todos'
const filters = {
all: todos => todos,
active: todos => todos.filter(todo => !todo.done),
completed: todos => todos.filter(todo => todo.done)
}
const defalutList = [
{ text: '78406346432', done: false },
{ text: '78406305165_JHJ42194', done: false },
{ text: '78406347272', done: false },
{ text: '78406346782_DIM896002168', done: true },
{ text: 'vue', done: true },
{ text: 'element-ui', done: true },
{ text: 'axios', done: true },
{ text: 'webpack', done: true }
]
export default {
components: { Todo },
filters: {
pluralize: (n, w) => n === 1 ? w : w + ' ',
capitalize: s => s.charAt(0).toUpperCase() + s.slice(1)
},
data() {
return {
visibility: 'all',
filters,
// todos: JSON.parse(window.localStorage.getItem(STORAGE_KEY)) || defalutList
todos: []
}
},
computed: {
allChecked() {
return this.todos.every(todo => todo.done)
},
filteredTodos() {
return filters[this.visibility](this.todos)
},
remaining() {
return this.todos.filter(todo => !todo.done).length
}
},
mounted:function () {
this.trnList();
},
methods: {
setLocalStorage() {
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(this.todos))
},
addTodo(e) {
const text = e.target.value
if (text.trim()) {
this.todos.push({
text,
done: false
})
this.setLocalStorage()
}
e.target.value = ''
},
toggleTodo(val) {
val.done = !val.done
this.setLocalStorage()
},
deleteTodo(todo) {
this.todos.splice(this.todos.indexOf(todo), 1)
this.setLocalStorage()
},
editTodo({ todo, value }) {
todo.text = value
this.setLocalStorage()
},
clearCompleted() {
this.todos = this.todos.filter(todo => !todo.done)
this.setLocalStorage()
},
toggleAll({ done }) {
this.todos.forEach(todo => {
todo.done = done
this.setLocalStorage()
})
},
// 获取消息标签列表
trnList() {
const loading = this.$loading({
lock: true,
text: 'Loading',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.7)'
});
const _this = this
let para = {
billno: '',
customscode:'',
username:'',
trnmode:'',
unloadcode:'',
creattime:'',
startDate:'',
endDate:'',
pageNum: 1,
pageSize: 10
}
selectTrans(para).then((response) => {
const res = response.data
if (res.code !== '200') {
return _this.$message.error('获取消息收发记录,失败!')
}
// // 获取列表数据
let tableData = res.data.list
if (tableData){
for (let item of tableData) {
let todoListItem = {text: item.billno, done: false}
if (item.dstatus === '001') {
todoListItem.done = true;
}else{
todoListItem.done = false;
}
_this.todos.push(todoListItem)
}
}
// // 获取列表的总记录数
// _this.total = res.data.total
_this.$message.success('获取消息收发记录,成功!')
}).catch(error => {
// 关闭加载
_this.$message.error(error.toString())
}).finally(()=>{
loading.close();
})
},
}
}
</script>
<style lang="scss">
@import '~@/views/dashboard/components/TodoList/index.scss';
</style>
... ...
<template>
<div :class="className" :style="{height:height,width:width}" />
</template>
<script>
import echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import resize from '@/views/dashboard/components/mixins/resize'
export default {
mixins: [resize],
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '350px'
},
autoResize: {
type: Boolean,
default: true
},
chartData: {
type: Object,
required: true
}
},
data() {
return {
chart: null
}
},
watch: {
chartData: {
deep: true,
handler(val) {
this.setOptions(val)
}
}
},
mounted() {
this.$nextTick(() => {
this.initChart()
})
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart() {
this.chart = echarts.init(this.$el, 'macarons')
this.setOptions(this.chartData)
},
setOptions({ lastWeek, thisWeek, lastYear,thisYear} = {}) {
this.chart.setOption({
xAxis: {
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
boundaryGap: true,
type: 'category',
axisTick: {
show: true
}
},
grid: {
left: 10,
right: 10,
bottom: 20,
top: 30,
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
padding: [5, 10]
},
yAxis: {
type: 'value',
axisTick: {
show: false
}
},
legend: {
data: ['本周总申报单量', '上周总申报单量','本周总申报货量','上周总申报货量']
},
series: [{
name: '本周总申报单量', itemStyle: {
normal: {
color: '#FF005A',
lineStyle: {
color: '#FF005A',
width: 2
}
}
},
smooth: true,
type: 'line',
data: thisWeek.totalCount,
animationDuration: 2800,
animationEasing: 'cubicInOut'
},
{
name: '上周总申报单量',
smooth: true,
type: 'line',
data: lastWeek.totalCount,
animationDuration: 2800,
animationEasing: 'cubicInOut'
},
{
name: '本周总申报货量',
smooth: true,
type: 'bar',
itemStyle: {
normal: {
color: '#3888fa',
lineStyle: {
color: '#3888fa',
width: 2
},
areaStyle: {
color: '#f3f8ff'
}
}
},
data: thisWeek.totalWeight,
animationDuration: 2800,
animationEasing: 'quadraticOut'
},
{
name: '上周总申报货量',
smooth: true,
type: 'bar',
stack: 'Ad',
emphasis: {
focus: 'series'
},
data: lastWeek.totalWeight,
animationDuration: 2800,
animationEasing: 'quadraticOut'
},
]
})
}
}
}
</script>
... ...
<template>
<div :class="className" :style="{height:height,width:width}" />
</template>
<script>
import echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import resize from '@/views/dashboard/components/mixins/resize'
export default {
mixins: [resize],
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '350px'
},
autoResize: {
type: Boolean,
default: true
},
chartData: {
type: Object,
required: true
}
},
data() {
return {
chart: null
}
},
watch: {
chartData: {
deep: true,
handler(val) {
this.setOptions(val)
}
}
},
mounted() {
this.$nextTick(() => {
this.initChart()
})
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart() {
this.chart = echarts.init(this.$el, 'macarons')
this.setOptions(this.chartData)
},
setOptions({ lastWeek, thisWeek, lastYear,thisYear} = {}) {
this.chart.setOption({
xAxis: {
data: ['一月', '二月', '三月', '四月', '五月', '六月', '七月','八月','九月','十月','十一月','十二月'],
boundaryGap: true,
type: 'category',
axisTick: {
show: true
}
},
grid: {
left: 10,
right: 10,
bottom: 20,
top: 30,
containLabel: true
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
},
padding: [5, 10]
},
yAxis: {
type: 'value',
axisTick: {
show: false
}
},
legend: {
data: ['本年总申报单量', '去年总申报单量','本年总申报货量','去年总申报货量']
},
series: [{
name: '本年总申报单量', itemStyle: {
normal: {
color: '#FF005A',
lineStyle: {
color: '#FF005A',
width: 2
}
}
},
smooth: true,
type: 'line',
data: thisYear.totalCount,
animationDuration: 2800,
animationEasing: 'cubicInOut'
},
{
name: '去年总申报单量',
smooth: true,
type: 'line',
data: lastYear.totalCount,
animationDuration: 2800,
animationEasing: 'cubicInOut'
},
{
name: '本年总申报货量',
smooth: true,
type: 'bar',
itemStyle: {
normal: {
color: '#3888fa',
lineStyle: {
color: '#3888fa',
width: 2
},
areaStyle: {
color: '#f3f8ff'
}
}
},
data: thisYear.totalWeight,
animationDuration: 2800,
animationEasing: 'quadraticOut'
},
{
name: '去年总申报货量',
smooth: true,
type: 'bar',
stack: 'Ad',
emphasis: {
focus: 'series'
},
data: lastYear.totalWeight,
animationDuration: 2800,
animationEasing: 'quadraticOut'
},
]
})
}
}
}
</script>
... ...
... ... @@ -883,6 +883,7 @@
},
// 获取消息标签列表
trnList() {
this.listLoading = true;
const _this = this
let para = Object.assign({}, this.formTrn)
para.creattime = ''
... ... @@ -899,6 +900,8 @@
}).catch(error => {
// 关闭加载
_this.$message.error(error.toString())
}).finally(()=>{
_this.listLoading = false;
})
},
//新增编辑弹框关闭重置
... ...
<template>
<div class="dashboard-editor-container">
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
<line-chart :chart-data="lineChartData" />
</el-row>
<el-row :gutter="8">
<el-col :xs="{span: 6}" :sm="{span: 6}" :md="{span: 6}" :lg="{span: 6}" :xl="{span: 6}" style="margin-bottom:30px;">
<todo-list />
</el-col>
<el-col :xs="{span: 18}" :sm="{span: 18}" :md="{span: 18}" :lg="{span: 18}" :xl="{span: 18}" style="margin-bottom:30px;background:#fff">
<week-line-chart :chart-data="lineChartData" />
</el-col>
</el-row>
</div>
</template>
<script>
import LineChart from './dashboard/YearLineChart'
import WeekLineChart from './dashboard/WeekLineChart'
import TodoList from './dashboard/TodoList'
import {analysisAPI} from "@/api/trn";
export default {
name: 'transDashboard',
components: {
LineChart,
TodoList,
WeekLineChart
},
data() {
return {
lineChartData: {
lastWeek:{totalCount:[],totalWeight:[]},
thisWeek:{totalCount:[],totalWeight:[]},
lastYear:{totalCount:[],totalWeight:[]},
thisYear:{totalCount:[],totalWeight:[]}
}
}
},
methods: {
getAnalysis:function () {
const loading = this.$loading({
lock: true,
text: '正在加载统计数据',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.6)'
});
analysisAPI().then(res =>{
const result = res.data;
if (result.code === '200') {
this.lineChartData = this.formatAnalysisData(result)
this.$message.success('获取数据成功')
} else {
this.$message.error('获取数据成功失败,请稍后重试')
}
}).catch(err => {
this.$message.error(err.toString())
}).finally(()=>{
loading.close()
})
},
formatAnalysisData:function transformData(originalData) {
const analysisData = {
thisWeek: { totalWeight: [], totalCount: [] },
lastWeek: { totalWeight: [], totalCount: [] },
lastYear: { totalWeight: [], totalCount: [] },
thisYear: { totalWeight: [], totalCount: [] },
};
originalData.data.forEach(item => {
switch (item.type) {
case 'thisWeek':
analysisData.thisWeek.totalWeight.push(item.totalWeight);
analysisData.thisWeek.totalCount.push(item.totalCount);
break;
case 'lastWeek':
analysisData.lastWeek.totalWeight.push(item.totalWeight);
analysisData.lastWeek.totalCount.push(item.totalCount);
break;
case 'lastYear':
analysisData.lastYear.totalWeight.push(item.totalWeight);
analysisData.lastYear.totalCount.push(item.totalCount);
break;
case 'thisYear':
analysisData.thisYear.totalWeight.push(item.totalWeight);
analysisData.thisYear.totalCount.push(item.totalCount);
break;
default:
console.warn(`Unknown type encountered: ${item.type}`);
}
});
// Ensure that each array in 'lastYear' and 'thisYear' has 12 elements for consistency.
// Fill missing months with zeros if necessary.
// const months = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'];
// months.forEach(month => {
// if (!analysisData.lastYear[month]) {
// analysisData.lastYear[month] = { totalWeight: Array(12).fill(0), totalCount: Array(12).fill(0) };
// }
// if (!analysisData.thisYear[month]) {
// analysisData.thisYear[month] = { totalWeight: Array(12).fill(0), totalCount: Array(12).fill(0) };
// }
// });
console.log(JSON.stringify(analysisData))
return analysisData;
}
},
mounted:function () {
this.getAnalysis();
}
}
</script>
<style lang="scss" scoped>
.dashboard-editor-container {
padding: 32px;
background-color: rgb(240, 242, 245);
position: relative;
.github-corner {
position: absolute;
top: 0px;
border: 0;
right: 0;
}
.chart-wrapper {
background: #fff;
padding: 16px 16px 0;
margin-bottom: 32px;
}
}
@media (max-width:1024px) {
.chart-wrapper {
padding: 6px;
}
}
</style>
... ...