统计(未完)

This commit is contained in:
小陌 2024-01-05 19:03:07 +08:00
parent 380e6b891d
commit 9d266b969e
12 changed files with 339 additions and 609 deletions

View File

@ -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'">

View 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>

View File

@ -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) {

View File

@ -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>

View File

@ -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');

View File

@ -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);

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>