统计(未完)
This commit is contained in:
parent
380e6b891d
commit
9d266b969e
@ -85,7 +85,13 @@
|
||||
<x-editor v-model="data[item.name]" v-bind="item.options"></x-editor>
|
||||
</template>
|
||||
<template v-else-if="item.component == 'text'">
|
||||
<el-link type="info" :underline="false" v-copy="data[item.name]">{{ data[item.name] }}</el-link>
|
||||
<el-text v-bind="item.options" v-copy="data[item.name]">{{ data[item.name] }}</el-text>
|
||||
</template>
|
||||
<template v-else-if="item.component == 'link'">
|
||||
<el-link v-bind="item.options">{{ data[item.name] }}</el-link>
|
||||
</template>
|
||||
<template v-else-if="item.component == 'button'">
|
||||
<el-button v-bind="item.options">{{ data[item.name] }}</el-button>
|
||||
</template>
|
||||
<!-- avatar -->
|
||||
<template v-else-if="item.component == 'avatar'">
|
||||
|
184
src/components/xStat/components/1.vue
Normal file
184
src/components/xStat/components/1.vue
Normal file
@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<el-container>
|
||||
<el-header v-if="this.date || dateGroup.length > 0">
|
||||
<div class="left-panel">
|
||||
<el-radio-group v-model="dateType" v-if="dateGroup.length > 0" @change="changedateGroup" style="margin-right: 15px;">
|
||||
<el-radio-button v-for="item in dateGroup" :key="item.value" :label="item.text" :name="item.value"></el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-date-picker class="hidden-sm-and-down" v-if="this.date" @change="changedate" format="YYYY-MM-DD HH:mm" v-model="date" type="datetimerange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
|
||||
</div>
|
||||
</el-header>
|
||||
<el-main>
|
||||
<el-card shadow="never" v-if="statistic.length > 0 || chartList.length > 0" class="xcard">
|
||||
<el-scrollbar>
|
||||
<div class="number-data">
|
||||
<div class="item" v-for="(s, index) in statistic" :key="index">
|
||||
<x-statistic :title="s.title" :value="s.value" :description="s.description" :tips="s.tips" groupSeparator>
|
||||
<x-trend v-model="s.trend" v-if="s.trend"></x-trend>
|
||||
</x-statistic>
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
<div class="chart" v-if="chartList.length > 0">
|
||||
<el-row>
|
||||
<el-col :span="c.span || 12" v-for="(c, index) in chartList" :key="index">
|
||||
<xEcharts :height="c.height ? Number(c.height) ? Number(c.height) + 'px' : c.height : '250px'" :option="c.option"></xEcharts>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card shadow="never" v-if="table && table.column.length > 0" class="xcard">
|
||||
<xTable ref="table" :data="table.data" :api="table.api" :tableColumn="table.column" :hideDo="table.hideDo || true" :hidePagination="table.hidePagination || true" :height="table.height || 'auto'">
|
||||
<el-table-column type="index" width="50" fixed />
|
||||
</xTable>
|
||||
</el-card>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import xEcharts from '@/components/xEcharts';
|
||||
import xStatistic from '@/components/xStatistic';
|
||||
export default {
|
||||
name: 'chartlist',
|
||||
components: {
|
||||
xEcharts,
|
||||
xStatistic,
|
||||
},
|
||||
props: {
|
||||
name: { type: String, default: "" },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dateGroup: [
|
||||
|
||||
],
|
||||
chartList: [
|
||||
|
||||
],
|
||||
statistic: [
|
||||
|
||||
],
|
||||
table: {
|
||||
api: null,
|
||||
height: 0,
|
||||
data: [],
|
||||
column: [],
|
||||
},
|
||||
dateType: '',
|
||||
date: null,
|
||||
statName: this.$route.meta.tablename,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
//监听从props里拿到值了
|
||||
date() {
|
||||
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
const now = new Date();
|
||||
const lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0);
|
||||
lastDay.setHours(23, 59, 0, 0);
|
||||
this.date = [new Date(now.getFullYear(), now.getMonth(), 1, 0, 0), lastDay];
|
||||
if (this.name) {
|
||||
this.statName = this.name || this.$route.meta.tablename;
|
||||
}
|
||||
this.loaddata();
|
||||
},
|
||||
methods: {
|
||||
changedateGroup() {
|
||||
this.dateGroup.forEach((item) => {
|
||||
if (this.dateType === item.text) {
|
||||
this.date = item.value;
|
||||
this.loaddata();
|
||||
}
|
||||
})
|
||||
},
|
||||
changedate() {
|
||||
this.loaddata()
|
||||
},
|
||||
loaddata() {
|
||||
//判断是否开启自定义列
|
||||
if (this.statName) {
|
||||
this.$http.get('stat/admin/get', { name: this.statName, date: this.date }).then((res) => {
|
||||
if (res.code == 200) {
|
||||
Object.assign(this.$data, res.data);
|
||||
this.dateType = '';
|
||||
this.dateGroup.forEach((item) => {
|
||||
if (new Date(item.value[0]).getTime() == new Date(this.date[0]).getTime() && new Date(item.value[1]).getTime() == new Date(this.date[1]).getTime()) {
|
||||
this.dateType = item.text;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.xcard {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.xcard:deep(.el-card__body) {
|
||||
padding: 10px
|
||||
}
|
||||
.number-data {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.number-data .item {
|
||||
flex: 1;
|
||||
border-right: 1px solid #f0f0f0;
|
||||
padding: 0 20px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.number-data .item:last-child {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.number-data .item h2 {
|
||||
font-size: 12px;
|
||||
color: #787a7d;
|
||||
font-weight: normal;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.number-data .item h2 i {
|
||||
margin-left: 5px;
|
||||
color: #8cc5ff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.number-data .item p {
|
||||
font-size: 20px;
|
||||
color: #121315;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.chart {
|
||||
border-top: 1px solid #f0f0f0;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.dark .number-data .item {
|
||||
border-color: var(--el-border-color-light);
|
||||
}
|
||||
|
||||
.dark .number-data .item p {
|
||||
color: #d0d0d0;
|
||||
}
|
||||
|
||||
.dark .chart {
|
||||
border-color: var(--el-border-color-light);
|
||||
}
|
||||
</style>
|
@ -3,64 +3,47 @@
|
||||
-->
|
||||
<template>
|
||||
<div class="x-stat">
|
||||
<component :is="componentType" :title="config.name || '查看统计'" v-model="visible" :size="size" :style="style" @closed="$emit('closed')">
|
||||
<component :is="componentType" :title="lable || '查看统计'" v-model="visible" :size="size" :style="style" @closed="$emit('closed')">
|
||||
<el-main>
|
||||
<el-skeleton v-if="loading" :rows="4" />
|
||||
<stat_1 :name="value"></stat_1>
|
||||
</el-main>
|
||||
<template #footer>
|
||||
|
||||
</template>
|
||||
<template #footer> </template>
|
||||
</component>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
.x-stat:deep(.el-drawer) .el-drawer__footer {
|
||||
text-align: left;
|
||||
border-top: 1px solid var(--el-border-color-light);
|
||||
padding: 10px 18px;
|
||||
.x-stat .el-main:first-of-type {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.x-stat:deep(.el-main) {
|
||||
padding: 0 20px 0px 20px;
|
||||
}
|
||||
|
||||
.x-stat:deep(.el-input) .el-input__wrapper {
|
||||
min-width: 50px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
import stat_1 from './components/1';
|
||||
export default {
|
||||
emits: ['success', 'closed'],
|
||||
props: {
|
||||
column: { type: Array, default: () => [] },
|
||||
name: { type: String, default: "id" },
|
||||
name: { type: String, default: "" },
|
||||
component: { type: String, default: "" },
|
||||
},
|
||||
components: {
|
||||
stat_1
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
mode: "plus",
|
||||
lable: "",
|
||||
value: this.name,
|
||||
token: '',
|
||||
key: this.name,
|
||||
titleMap: {
|
||||
plus: '新增',
|
||||
edit: '编辑'
|
||||
},
|
||||
data: {},
|
||||
style: {},
|
||||
config: {
|
||||
column: this.column,
|
||||
labelPosition: "right",
|
||||
labelWidth: "120px",
|
||||
size: "medium",
|
||||
submitinfokey: "info",
|
||||
url: '',
|
||||
merge: false, // 远程数据时, 是否合并data
|
||||
submitname: '保存'
|
||||
},
|
||||
size: 900,
|
||||
visible: false,
|
||||
isSaveing: false,
|
||||
type: 'dialog',
|
||||
}
|
||||
},
|
||||
@ -71,11 +54,11 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
componentType() {
|
||||
return this.type == 'drawer' ? 'el-drawer' : 'x-dialog';
|
||||
return this.type == 'containe' ? 'el-containe' : (this.type == 'drawer' ? 'el-drawer' : 'x-dialog');
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
this.getComponentType(this.component);
|
||||
},
|
||||
methods: {
|
||||
getComponentType(type) {
|
||||
@ -83,92 +66,54 @@ export default {
|
||||
return this;
|
||||
},
|
||||
// 显示
|
||||
open(mode = 'plus') {
|
||||
this.mode = mode;
|
||||
open() {
|
||||
this.visible = true;
|
||||
return this;
|
||||
},
|
||||
// 表单提交方法
|
||||
submit() {
|
||||
|
||||
|
||||
this.$refs.formref.validate(async (valid) => {
|
||||
if (valid) {
|
||||
if (!this.config.url) {
|
||||
console.log(this.data)
|
||||
this.$alert('没有' + (this.config.name || '统计') + '数据相关配置', "提示", { type: 'error' });
|
||||
return;
|
||||
}
|
||||
|
||||
const data = {
|
||||
[this.config.submitinfokey || 'info']: this.data,
|
||||
};
|
||||
|
||||
if (this.key && typeof this.data[this.key] !== 'undefined') {
|
||||
Object.assign(data, { [this.key]: this.data[this.key] });
|
||||
}
|
||||
|
||||
if (this.token) {
|
||||
Object.assign(data, { token: this.token });
|
||||
}
|
||||
|
||||
this.isSaveing = true;
|
||||
this.$http.post(this.config.url, data).then((res) => {
|
||||
this.isSaveing = false;
|
||||
if (res.code == 200) {
|
||||
this.visible = false;
|
||||
this.$emit('success', res.data, this.mode, res.message || "操作成功");
|
||||
return;
|
||||
}
|
||||
this.$alert(res.message, "提示", { type: 'error' });
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
// 配置
|
||||
setConfig(o) {
|
||||
Object.assign(this.config, o);
|
||||
Object.assign(this.$data, o);
|
||||
|
||||
if (typeof this.config.key !== 'undefined' && this.config.key) {
|
||||
this.key = this.config.key;
|
||||
}
|
||||
// 远程读取数据
|
||||
if (this.config.remoteurl) {
|
||||
this.loading = true;
|
||||
setTimeout(async () => {
|
||||
var res = await this.$http.post(this.config.remoteurl, { [this.key]: this.data[this.key] })
|
||||
if (res.code == 200) {
|
||||
this.loading = false;
|
||||
if (res.data.config) {
|
||||
Object.assign(this.config, res.data.config);
|
||||
}
|
||||
// if (typeof this.config.key !== 'undefined' && this.config.key) {
|
||||
// this.key = this.config.key;
|
||||
// }
|
||||
// // 远程读取数据
|
||||
// if (this.config.remoteurl) {
|
||||
// this.loading = true;
|
||||
// setTimeout(async () => {
|
||||
// var res = await this.$http.post(this.config.remoteurl, { [this.key]: this.data[this.key] })
|
||||
// if (res.code == 200) {
|
||||
// this.loading = false;
|
||||
// if (res.data.config) {
|
||||
// Object.assign(this.config, res.data.config);
|
||||
// }
|
||||
|
||||
if (res.data.data) {
|
||||
this.config.merge ? Object.assign(this.data, res.data.data) : this.setData(res.data.data)
|
||||
}
|
||||
// if (res.data.data) {
|
||||
// this.config.merge ? Object.assign(this.data, res.data.data) : this.setData(res.data.data)
|
||||
// }
|
||||
|
||||
if (res.data.token) {
|
||||
this.token = res.data.token
|
||||
}
|
||||
// if (res.data.token) {
|
||||
// this.token = res.data.token
|
||||
// }
|
||||
|
||||
if (res.data.size) {
|
||||
this.size = res.data.size
|
||||
}
|
||||
// if (res.data.size) {
|
||||
// this.size = res.data.size
|
||||
// }
|
||||
|
||||
if (res.data.type && res.data.type !== this.type) {
|
||||
this.getComponentType(res.data.type)
|
||||
}
|
||||
// if (res.data.type && res.data.type !== this.type) {
|
||||
// this.getComponentType(res.data.type)
|
||||
// }
|
||||
|
||||
if (res.data.style) {
|
||||
this.style = res.data.style;
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.visible = false;
|
||||
this.$alert(res.message, "提示", { type: 'error' });
|
||||
}, 100)
|
||||
return false;
|
||||
}
|
||||
// if (res.data.style) {
|
||||
// this.style = res.data.style;
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
// this.visible = false;
|
||||
// this.$alert(res.message, "提示", { type: 'error' });
|
||||
// }, 100)
|
||||
// return false;
|
||||
// }
|
||||
},
|
||||
// 表单注入数据
|
||||
setData(data) {
|
||||
|
@ -12,7 +12,7 @@
|
||||
{{ tips }}
|
||||
</div>
|
||||
</template>
|
||||
<el-icon class="x-statistic-tips"><el-icon-question-filled/></el-icon>
|
||||
<el-icon class="x-statistic-tips"><el-icon-question-filled /></el-icon>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div class="x-statistic-content">
|
||||
@ -22,44 +22,75 @@
|
||||
</div>
|
||||
<div v-if="description || $slots.default" class="x-statistic-description">
|
||||
<slot>
|
||||
{{ description }}
|
||||
{{ description }}
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
title: { type: String, required: true, default: "" },
|
||||
value: { type: String, required: true, default: "" },
|
||||
prefix: { type: String, default: "" },
|
||||
suffix: { type: String, default: "" },
|
||||
description: { type: String, default: "" },
|
||||
tips: { type: String, default: "" },
|
||||
groupSeparator: { type: Boolean, default: false }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
export default {
|
||||
props: {
|
||||
title: { type: String, required: true, default: "" },
|
||||
value: { type: String, required: true, default: "" },
|
||||
prefix: { type: String, default: "" },
|
||||
suffix: { type: String, default: "" },
|
||||
description: { type: String, default: "" },
|
||||
tips: { type: String, default: "" },
|
||||
groupSeparator: { type: Boolean, default: false }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
cmtValue(){
|
||||
return this.groupSeparator ? this.$tool.groupSeparator(this.value) : this.value
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
cmtValue() {
|
||||
return this.groupSeparator ? this.$tool.groupSeparator(this.value) : this.value
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.x-statistic-title {font-size: 12px;color: #999;margin-bottom: 10px;display: flex;align-items: center;}
|
||||
.x-statistic-tips {margin-left: 5px;}
|
||||
.x-statistic-content {font-size: 20px;color: #333;}
|
||||
.x-statistic-content-value {font-weight: bold;}
|
||||
.x-statistic-content-prefix {margin-right: 5px;}
|
||||
.x-statistic-content-suffix {margin-left: 5px;font-size: 12px;}
|
||||
.x-statistic-description {margin-top: 10px;color: #999;}
|
||||
.x-statistic-title {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dark .x-statistic-content {color: #d0d0d0;}
|
||||
</style>
|
||||
.x-statistic-tips {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.x-statistic-content {
|
||||
font-size: 20px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.x-statistic-content-value {
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.x-statistic-content-prefix {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.x-statistic-content-suffix {
|
||||
margin-left: 5px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.x-statistic-description {
|
||||
margin-top: 10px;
|
||||
color: #999;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dark .x-statistic-content {
|
||||
color: #d0d0d0;
|
||||
}</style>
|
||||
|
@ -27,6 +27,12 @@
|
||||
<p v-else-if="item.columntype == 'button'">
|
||||
<el-button @click="handleClick(row, item)" :type="item.options.type || 'warning'" v-bind="item.options"> {{ row[item.name] }} </el-button>
|
||||
</p>
|
||||
<p v-else-if="item.columntype == 'link'">
|
||||
<el-link v-bind="item.options" @click="handleClick(row, item)"> {{ row[item.name] }} </el-link>
|
||||
</p>
|
||||
<p v-else-if="item.columntype == 'text'">
|
||||
<el-text v-bind="item.options" v-copy="row[item.name]"> {{ row[item.name] }} </el-text>
|
||||
</p>
|
||||
<p v-else-if="item.columntype == 'tag' || item.columntype == 'time'" @click="handleClick(row, item)" v-time.tip="row[item.name]"></p>
|
||||
<slot v-else :name="item.name">
|
||||
{{ item.columntype == 'select' && item.options && item.options.items ? getNameByValue(row[item.name], item.options.items) : row[item.name] }}
|
||||
@ -60,12 +66,17 @@ export default {
|
||||
// 打开编辑层
|
||||
else if (item.update && (item.update.url || item.update.name)) {
|
||||
var options = Object.assign({ name: item.update.name || item.label, remoteurl: item.update.url || 'table/getUpdate?name=' + item.update.name }, item.update);
|
||||
this.$emit('xtableupdate', row, options, 'update');
|
||||
this.$emit('xtablehandleClick', row, options, 'update');
|
||||
return;
|
||||
}
|
||||
// 统计
|
||||
else if (item.stat && (item.stat.value || item.stat.key)) {
|
||||
this.$emit('xtablehandleClick', row, item.stat, 'stat');
|
||||
return;
|
||||
}
|
||||
// 打开表格
|
||||
else if (item.table && (item.table.url || item.table.name)) {
|
||||
this.$emit('xtableupdate', row, {
|
||||
this.$emit('xtablehandleClick', row, {
|
||||
name: item.table.name || item.name,
|
||||
remoteurl: item.table.url || 'table/get?name=' + item.table.name
|
||||
}, item.table.type || 'dialog', 'table');
|
||||
|
@ -8,13 +8,13 @@
|
||||
<el-table-column :align="item.align || 'left'" :label="item.label" v-if="item.column && item.column.length > 0">
|
||||
<el-table-column v-for="(items, indexs) in item.column" :key="indexs" :align="items.align || 'left'" :column-key="items.prop || items.name" :label="items.label" :prop="items.prop || items.name" :width="items.width || 'auto'" :min-width="items.minWidth || 'auto'" :sortable="items.sortable" :fixed="items.fixed" :filters="items.filters" :filter-method="remoteFilter || !items.filters ? null : filterHandler" :show-overflow-tooltip="items.showOverflowTooltip">
|
||||
<template #default="{ row }">
|
||||
<columnItem :row="row" :item="items" @xtableupdate="xtableupdate"> </columnItem>
|
||||
<columnItem :row="row" :item="items" @xtablehandleClick="xtablehandleClick"> </columnItem>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
<el-table-column v-else-if="!item.hide && (item.name || item.prop)" :align="item.align || 'left'" :column-key="item.prop || item.name" :label="item.label" :prop="item.prop || item.name" :width="item.width || 'auto'" :min-width="item.minWidth || 'auto'" :sortable="item.sortable" :fixed="item.fixed" :filters="item.filters" :filter-method="remoteFilter || !item.filters ? null : filterHandler" :show-overflow-tooltip="item.showOverflowTooltip">
|
||||
<template #default="{ row }">
|
||||
<columnItem :row="row" :item="item" @xtableupdate="xtableupdate"> </columnItem>
|
||||
<columnItem :row="row" :item="item" @xtablehandleClick="xtablehandleClick"> </columnItem>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
@ -35,6 +35,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<x-update v-if="tableUpdateKey" :name="tableUpdateKey" ref="xtableupdate" @success="handleSuccess" @closed="tableUpdateKey = ''"></x-update>
|
||||
<x-stat v-if="tableStatKey" :name="tableStatKey" ref="xtablestat" @closed="tableStatKey = ''"></x-stat>
|
||||
<xTabledialog v-if="xtabledialog" :name="xtabledialog" ref="xtabledialog" v-model="xtabledialog"></xTabledialog>
|
||||
</template>
|
||||
|
||||
@ -169,6 +170,7 @@ export default {
|
||||
customColumnShow: false,
|
||||
tableUpdateKey: '',
|
||||
xtabledialog: '',
|
||||
tableStatKey: '',
|
||||
summary: {},
|
||||
visibleInfo: {},
|
||||
config: {
|
||||
@ -235,7 +237,7 @@ export default {
|
||||
getSelection(val) {
|
||||
this.selection = val;
|
||||
},
|
||||
xtableupdate(row, options, type = 'update') {
|
||||
xtablehandleClick(row, options, type = 'update') {
|
||||
var componenttype = options.type || 'dialog';
|
||||
if (type == 'update') {
|
||||
this.tableUpdateKey = options.name || this.name;
|
||||
@ -244,6 +246,13 @@ export default {
|
||||
})
|
||||
return;
|
||||
}
|
||||
else if (type == 'stat') {
|
||||
this.tableStatKey = options.value || this.name;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.xtablestat.open().setData(row).setConfig(options);
|
||||
})
|
||||
return;
|
||||
}
|
||||
this.xtabledialog = options.name || this.name;
|
||||
this.$nextTick(() => {
|
||||
this.$refs.xtabledialog.open().setData(row).getComponentType(componenttype).setConfig(options);
|
||||
|
@ -294,7 +294,7 @@ export default {
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
/* ::v-deep .el-tabs{
|
||||
--el-tabs-header-height: 100px;
|
||||
} */
|
||||
::v-deep .el-tabs{
|
||||
--el-tabs-header-height: 120px;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,181 +1,16 @@
|
||||
<template>
|
||||
<el-container>
|
||||
<el-header v-if="this.date || dateGroup.length > 0">
|
||||
<div class="left-panel">
|
||||
<el-radio-group v-model="dateType" v-if="dateGroup.length > 0" @change="changedateGroup" style="margin-right: 15px;">
|
||||
<el-radio-button v-for="item in dateGroup" :key="item.value" :label="item.text" :name="item.value"></el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-date-picker class="hidden-sm-and-down" v-if="this.date" @change="changedate" format="YYYY-MM-DD HH:mm" v-model="date" type="datetimerange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
|
||||
</div>
|
||||
</el-header>
|
||||
<el-main>
|
||||
<el-card shadow="never" v-if="statistic.length > 0" class="xcard">
|
||||
<div class="number-data">
|
||||
<div class="item" v-for="(s, index) in statistic" :key="index">
|
||||
<x-statistic :title="s.title" :value="s.value" :description="s.description" :tips="s.tips" groupSeparator>
|
||||
<x-trend v-model="s.trend" v-if="s.trend"></x-trend>
|
||||
</x-statistic>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chart" v-if="chartList.length > 0">
|
||||
<el-row>
|
||||
<el-col :span="c.span || 12" v-for="(c, index) in chartList" :key="index">
|
||||
<xEcharts :height="c.height ? Number(c.height) ? Number(c.height) + 'px' : c.height : '250px'" :option="c.option"></xEcharts>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card shadow="never" v-if="table && table.column.length > 0" class="xcard">
|
||||
<xTable ref="table" :data="table.data" :api="table.api" :tableColumn="table.column" :hideDo="table.hideDo || true" :hidePagination="table.hidePagination || true" :height="table.height || 'auto'">
|
||||
<el-table-column type="index" width="50" fixed />
|
||||
</xTable>
|
||||
</el-card>
|
||||
</el-main>
|
||||
</el-container>
|
||||
<x-stat :name="statName" component="containe"></x-stat>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import xEcharts from '@/components/xEcharts';
|
||||
import xStatistic from '@/components/xStatistic';
|
||||
export default {
|
||||
name: 'chartlist',
|
||||
components: {
|
||||
xEcharts,
|
||||
xStatistic,
|
||||
},
|
||||
props: {
|
||||
name: { type: String, default: "" },
|
||||
},
|
||||
name: 'stat',
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
dateGroup: [
|
||||
|
||||
],
|
||||
chartList: [
|
||||
|
||||
],
|
||||
statistic: [
|
||||
|
||||
],
|
||||
table: {
|
||||
api: null,
|
||||
height: 0,
|
||||
data: [],
|
||||
column: [],
|
||||
},
|
||||
dateType: '',
|
||||
date: null,
|
||||
statName: this.$route.meta.tablename,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
//监听从props里拿到值了
|
||||
date() {
|
||||
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
const now = new Date();
|
||||
const lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0);
|
||||
lastDay.setHours(23, 59, 0, 0);
|
||||
this.date = [new Date(now.getFullYear(), now.getMonth(), 1, 0, 0), lastDay];
|
||||
|
||||
if (this.name) {
|
||||
this.statName = this.name || this.$route.meta.tablename;
|
||||
}
|
||||
this.loaddata();
|
||||
},
|
||||
methods: {
|
||||
changedateGroup() {
|
||||
this.dateGroup.forEach((item) => {
|
||||
if (this.dateType === item.text) {
|
||||
this.date = item.value;
|
||||
this.loaddata();
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
changedate() {
|
||||
this.loaddata()
|
||||
},
|
||||
loaddata() {
|
||||
//判断是否开启自定义列
|
||||
if (this.statName) {
|
||||
this.$http.get('stat/admin/get', { name: this.statName, date: this.date }).then((res) => {
|
||||
if (res.code == 200) {
|
||||
Object.assign(this.$data, res.data);
|
||||
this.dateType = '';
|
||||
this.dateGroup.forEach((item) => {
|
||||
if (new Date(item.value[0]).getTime() == new Date(this.date[0]).getTime() && new Date(item.value[1]).getTime() == new Date(this.date[1]).getTime()) {
|
||||
this.dateType = item.text;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
mounted() {},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.xcard {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.xcard .el-card__body {
|
||||
padding: 10px
|
||||
}
|
||||
</style>
|
||||
<style scoped>
|
||||
|
||||
.number-data {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.number-data .item {
|
||||
flex: 1;
|
||||
border-right: 1px solid #f0f0f0;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.number-data .item:last-child {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.number-data .item h2 {
|
||||
font-size: 12px;
|
||||
color: #787a7d;
|
||||
font-weight: normal;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.number-data .item h2 i {
|
||||
margin-left: 5px;
|
||||
color: #8cc5ff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.number-data .item p {
|
||||
font-size: 20px;
|
||||
color: #121315;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.chart {
|
||||
border-top: 1px solid #f0f0f0;
|
||||
margin-top: 20px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.dark .number-data .item {
|
||||
border-color: var(--el-border-color-light);
|
||||
}
|
||||
|
||||
.dark .number-data .item p {
|
||||
color: #d0d0d0;
|
||||
}
|
||||
|
||||
.dark .chart {
|
||||
border-color: var(--el-border-color-light);
|
||||
}</style>
|
||||
</script>
|
@ -1,225 +0,0 @@
|
||||
<template>
|
||||
<el-container>
|
||||
<el-aside :width="(aside.width || 160) + 'px'" v-if="aside.items.length > 0">
|
||||
<el-header>
|
||||
<el-input placeholder="输入关键字进行过滤" v-model="groupFilterText" clearable></el-input>
|
||||
</el-header>
|
||||
<el-main class="nopadding">
|
||||
<el-tree ref="group" class="menu" :node-key="aside.key || 'id'" :data="aside.items" :highlight-current="true" :expand-on-click-node="false" :filter-node-method="groupFilterNode" @node-click="groupClick"></el-tree>
|
||||
</el-main>
|
||||
</el-aside>
|
||||
<el-container>
|
||||
<el-header class="header-tabs" v-if="tabs.length > 0">
|
||||
<el-tabs type="card" v-model="search[tabskey]" @tab-change="tabChange">
|
||||
<el-tab-pane v-for="item in tabs" :key="item.value" :label="item.label" :name="item.value"> </el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-header>
|
||||
<el-header v-if="operation.plus || operation.batchdeletion || filter.length > 0">
|
||||
<div class="left-panel">
|
||||
<el-button v-if="operation.plus" type="primary" icon="el-icon-plus" @click="plus"></el-button>
|
||||
</div>
|
||||
<div class="right-panel" v-if="filter.length > 0 || stat.length > 0">
|
||||
<el-button v-for="(s, index) in stat" :key="index" class="hidden-xs-only" @click="openStat(s)" v-bind="s">{{ s.label }}</el-button>
|
||||
<xFilterBar v-if="filter.length > 0" v-model="search" :filterName="$route.meta.tablename" :options="filter" @filterChange="filterChange"> </xFilterBar>
|
||||
</div>
|
||||
</el-header>
|
||||
|
||||
<el-header style="height:120px;" v-if="typeof chartoption === 'object' && Object.keys(chartoption).length > 0">
|
||||
<xEcharts height="100%" :option="chartoption"></xEcharts>
|
||||
</el-header>
|
||||
|
||||
<el-main class="nopadding">
|
||||
<xTable ref="table" :tableColumn="column" :name="tablename" :params="search" :operationInfo="operation" :api="api" :row-key="key" :remoteSort="true" :remoteFilter="true" stripe>
|
||||
<el-table-column v-if="isselection" type="selection" width="48"></el-table-column>
|
||||
<el-table-column :label="operation.label || '操作'" :width="operation.width || 124" :fixed="operation.fixed || 'right'" :align="operation.align || 'left'" v-if="operation.edit || operation.delete">
|
||||
<template #default="scope">
|
||||
<el-button-group>
|
||||
<el-button v-if="operation.edit" :type="operation.edit.type || 'primary'" :size="operation.edit.size || 'small'" @click="operationEdit(scope.row, scope.$index)">{{ operation.edit.label || '编辑' }}</el-button>
|
||||
<el-popconfirm v-if="operation.delete" :title="operation.delete.title || '确定删除吗?'" @confirm="operationDelete(scope.row, scope.$index)">
|
||||
<template #reference>
|
||||
<el-button :type="operation.delete.type || 'info'" :size="operation.delete.size || 'small'">{{ operation.delete.label || '删除' }}</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</el-button-group>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</xTable>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
<x-update v-if="dialog.save" :column="column" :name="key" ref="saveDialog" @success="handleSuccess" @closed="dialog.save = false"></x-update>
|
||||
<x-stat v-if="dialog.stat" ref="xstatdialog" @closed="dialog.stat = false"></x-stat>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import xStat from './stat'
|
||||
import xFilterBar from '@/components/xFilterBar';
|
||||
import xEcharts from '@/components/xEcharts'
|
||||
export default {
|
||||
name: 'table_1',
|
||||
components: {
|
||||
xStat,
|
||||
xEcharts,
|
||||
xFilterBar
|
||||
},
|
||||
props: {
|
||||
name: { type: String, default: "" },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialog: {
|
||||
save: false,
|
||||
stat: false,
|
||||
},
|
||||
isselection: true,
|
||||
selection: [],
|
||||
column: [],
|
||||
aside: {
|
||||
items: []
|
||||
},
|
||||
filter: [],
|
||||
api: '',
|
||||
operation: {},
|
||||
key: 'id',
|
||||
search: {},
|
||||
tabs: [
|
||||
// {label:'所有', value:0},
|
||||
],
|
||||
stat: [],
|
||||
chartoption: {},
|
||||
tablename: this.$route.meta.tablename,
|
||||
tableurl: this.$route.meta.tableurl,
|
||||
groupFilterText: '',
|
||||
tabskey: '',
|
||||
tabsdefaultvalue: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.name) {
|
||||
this.tablename = this.name || this.$route.meta.tablename;
|
||||
}
|
||||
|
||||
//判断是否开启自定义列
|
||||
if (this.tablename || this.tableurl) {
|
||||
var awaitvar = this.tableurl ? this.$http.get(this.tableurl, {}, { cache: true }) : this.$api.system.table.get(this.tablename, { cache: this.$route.meta.tablecache || 0 });
|
||||
awaitvar.then((res) => {
|
||||
if (res.code == 200) {
|
||||
Object.assign(this.$data, res.data);
|
||||
if (res.data.tabsdefaultvalue && res.data.tabskey) {
|
||||
this.search[res.data.tabskey] = res.data.tabsdefaultvalue
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
filterObj() {
|
||||
const obj = []
|
||||
this.filter.forEach((item) => {
|
||||
if (item.component) {
|
||||
obj.push({
|
||||
name: item.value,
|
||||
label: item.label,
|
||||
component: item.component,
|
||||
options: item.options,
|
||||
})
|
||||
}
|
||||
})
|
||||
return obj
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
groupFilterText(val) {
|
||||
this.$refs.group.filter(val);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//树过滤
|
||||
groupFilterNode(value, data) {
|
||||
if (!value) return true;
|
||||
return data.label.indexOf(value) !== -1;
|
||||
},
|
||||
//树点击事件
|
||||
groupClick(data) {
|
||||
this.search[this.aside.searchkey || 'groupid'] = data[this.aside.key || 'id'];
|
||||
this.$refs.table.reload(this.search)
|
||||
},
|
||||
// 筛选回调
|
||||
filterChange(data) {
|
||||
var info = Object.assign({}, this.search, data)
|
||||
this.$refs.table.reload(info)
|
||||
},
|
||||
//标签切换
|
||||
tabChange() {
|
||||
this.$refs.table.reload(this.search)
|
||||
},
|
||||
//本地更新数据
|
||||
handleSuccess(data, mode, message) {
|
||||
if (mode == 'edit') {
|
||||
if (data) {
|
||||
this.$refs.table.tableData.filter(item => item[this.key] === data[this.key]).forEach(item => {
|
||||
Object.assign(item, data, data)
|
||||
})
|
||||
} else {
|
||||
this.$refs.table.refresh()
|
||||
}
|
||||
} else {
|
||||
if (data) {
|
||||
this.$refs.table.tableData.unshift(data)
|
||||
} else {
|
||||
this.$refs.table.reload({})
|
||||
}
|
||||
}
|
||||
this.$message.success(message || "操作成功")
|
||||
return;
|
||||
},
|
||||
//增加
|
||||
plus() {
|
||||
this.dialog.save = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.saveDialog.open('plus').getComponentType(this.operation.plus.component).setData({}).setConfig(this.operation.plus)
|
||||
})
|
||||
},
|
||||
//编辑
|
||||
operationEdit(row) {
|
||||
this.dialog.save = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.saveDialog.open('edit').getComponentType(this.operation.edit.component).setData(row).setConfig(this.operation.edit)
|
||||
})
|
||||
},
|
||||
//打开统计
|
||||
openStat(o) {
|
||||
this.dialog.stat = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.xstatdialog.open().setData(o);
|
||||
})
|
||||
},
|
||||
//删除
|
||||
async operationDelete(row, index) {
|
||||
|
||||
const key = typeof this.operation.delete.key !== 'undefined' && this.operation.delete.key ? this.operation.delete.key : this.key;
|
||||
var res = await this.$http.post(this.operation.delete.url, { [key]: row[key], index: index })
|
||||
if (res.code == 200) {
|
||||
this.$refs.table.tableData.splice(index, 1);
|
||||
return;
|
||||
}
|
||||
this.$alert(res.message, "提示", { type: 'error' });
|
||||
},
|
||||
//表格选择后回调事件
|
||||
selectionChange(selection) {
|
||||
this.selection = selection;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
@media (max-width: 992px) {
|
||||
|
||||
.adminui-main>.el-container>.el-container>.el-header .right-panel {
|
||||
display: block;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
@ -1,32 +0,0 @@
|
||||
<template>
|
||||
<el-drawer :title="info.title || info.label" v-model="visible" :size="1000" destroy-on-close @closed="$emit('closed')">
|
||||
<stat :name="info.value || info.name"></stat>
|
||||
</el-drawer>
|
||||
</template>
|
||||
<script>
|
||||
import stat from '@/views/system/stat';
|
||||
export default {
|
||||
emits: ['success', 'closed'],
|
||||
props: {},
|
||||
components: {
|
||||
stat,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
info: {},
|
||||
visible: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//显示
|
||||
open(){
|
||||
this.visible = true;
|
||||
return this;
|
||||
},
|
||||
//表单注入数据
|
||||
setData(info){
|
||||
this.info = info;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
@ -43,13 +43,11 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import xStat from './stat'
|
||||
import xFilterBar from '@/components/xFilterBar';
|
||||
import xEcharts from '@/components/xEcharts'
|
||||
export default {
|
||||
name: 'table_1',
|
||||
components: {
|
||||
xStat,
|
||||
xEcharts,
|
||||
xFilterBar
|
||||
},
|
||||
@ -194,7 +192,7 @@ export default {
|
||||
openStat(o) {
|
||||
this.dialog.stat = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.xstatdialog.open().setData(o);
|
||||
this.$refs.xstatdialog.open().setConfig(o);
|
||||
})
|
||||
},
|
||||
//删除
|
||||
@ -224,6 +222,7 @@ export default {
|
||||
background-color: var(--el-fill-color-blank);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.container:deep(.el-header) {
|
||||
padding: 0 20px;
|
||||
}
|
||||
@ -239,10 +238,9 @@ export default {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.container:deep(.el-header) .right-panel > * + * {
|
||||
.container:deep(.el-header) .right-panel>*+* {
|
||||
margin: 0px 0px 0 10px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -1,32 +0,0 @@
|
||||
<template>
|
||||
<el-drawer :title="info.title || info.label" v-model="visible" :size="1000" destroy-on-close @closed="$emit('closed')">
|
||||
<stat :name="info.value || info.name"></stat>
|
||||
</el-drawer>
|
||||
</template>
|
||||
<script>
|
||||
import stat from '@/views/system/stat';
|
||||
export default {
|
||||
emits: ['success', 'closed'],
|
||||
props: {},
|
||||
components: {
|
||||
stat,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
info: {},
|
||||
visible: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//显示
|
||||
open(){
|
||||
this.visible = true;
|
||||
return this;
|
||||
},
|
||||
//表单注入数据
|
||||
setData(info){
|
||||
this.info = info;
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user