vue2-client 1.8.47 → 1.8.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,155 +1,226 @@
1
- <template>
2
- <div class="chart-card">
3
- <a-row type="flex" align="middle" justify="center" :gutter="16">
4
- <a-col>
5
- 分组条件:<a-select v-model="selectedGroup" style="width: 200px" @change="updateCharts">
6
- <a-select-option v-for="option in groupOptions" :key="option" :value="option">{{ option }}</a-select-option>
7
- </a-select>
8
- </a-col>
9
- <a-col>
10
- 数值列:<a-select v-model="selectedValues" mode="multiple" style="width: 200px" @change="updateCharts">
11
- <a-select-option v-for="option in valueOptions" :key="option" :value="option">{{ option }}</a-select-option>
12
- </a-select>
13
- </a-col>
14
- </a-row>
15
- <a-divider/>
16
- <a-row type="flex" align="middle" justify="space-around" :gutter="24">
17
- <a-col>
18
- <div ref="pieChart" class="chart-content"></div>
19
- </a-col>
20
- <a-col>
21
- <div ref="columnChart" class="chart-content"></div>
22
- </a-col>
23
- </a-row>
24
- </div>
25
- </template>
26
-
27
- <script>
28
- import { Pie, Column } from '@antv/g2plot'
29
-
30
- export default {
31
- data () {
32
- return {
33
- selectedGroup: null,
34
- groupOptions: [],
35
- valueOptions: [],
36
- selectedValues: [], // 更新为数组,支持多选
37
- pieChart: null,
38
- columnChart: null,
39
- }
40
- },
41
- mounted () {
42
- this.initData()
43
- },
44
- props: {
45
- rawData: {
46
- type: Array,
47
- required: true
48
- }
49
- },
50
- watch: {
51
- rawData: {
52
- deep: true,
53
- handler (newVal) {
54
- this.initData()
55
- }
56
- }
57
- },
58
- methods: {
59
- initData () {
60
- this.initializeOptions()
61
- this.selectedGroup = this.groupOptions[0]
62
- if (this.valueOptions.length > 0) {
63
- this.selectedValues = [this.valueOptions[0]] // 默认选择第一个数值列
64
- }
65
- this.updateCharts()
66
- },
67
- initializeOptions () {
68
- if (this.rawData.length > 0) {
69
- const firstRow = this.rawData[0]
70
- this.groupOptions = Object.keys(firstRow).filter(key => typeof firstRow[key] === 'string')
71
- this.valueOptions = Object.keys(firstRow).filter(key => typeof firstRow[key] === 'number')
72
- }
73
- },
74
- updateCharts () {
75
- this.renderPieChart()
76
- this.renderColumnChart()
77
- },
78
- renderPieChart () {
79
- const transformedData = this.transformDataForChart(true) // 传递参数以指示是否为饼图
80
- if (this.pieChart) {
81
- this.pieChart.changeData(transformedData)
82
- } else {
83
- this.pieChart = new Pie(this.$refs.pieChart, {
84
- data: transformedData,
85
- angleField: 'value',
86
- colorField: 'category',
87
- radius: 0.8,
88
- forceFit: true,
89
- title: {
90
- visible: true,
91
- text: '多色饼图',
92
- },
93
- description: {
94
- visible: true,
95
- text:
96
- '指定颜色映射字段(colorField),饼图切片将根据该字段数据显示为不同的颜色。指定颜色需要将color配置为一个数组。\n当把饼图label的类型设置为inner时,标签会显示在切片内部。设置offset控制标签的偏移值。',
97
- },
98
- label: {
99
- visible: true,
100
- type: 'inner',
101
- },
102
- })
103
- this.pieChart.render()
104
- }
105
- },
106
- renderColumnChart () {
107
- const transformedData = this.transformDataForChart(false) // 非饼图
108
- if (this.columnChart) {
109
- this.columnChart.changeData(transformedData)
110
- } else {
111
- this.columnChart = new Column(this.$refs.columnChart, {
112
- data: transformedData,
113
- xField: 'category',
114
- yField: 'value',
115
- seriesField: 'type', // 使用类型字段来区分不同的数值列
116
- isGroup: true,
117
- })
118
- this.columnChart.render()
119
- }
120
- },
121
- transformDataForChart (isPieChart) {
122
- if (isPieChart) {
123
- // 饼图数据转换逻辑:将选中的数值列汇总
124
- const totalByValue = this.selectedValues.map(valueKey => ({
125
- category: valueKey,
126
- value: this.rawData.reduce((sum, item) => sum + item[valueKey], 0),
127
- }))
128
- return totalByValue
129
- } else {
130
- // 柱状图数据转换逻辑:为每个分组条件和选中的数值列创建条目
131
- const transformedData = []
132
- this.rawData.forEach(item => {
133
- this.selectedValues.forEach(valueKey => {
134
- transformedData.push({
135
- category: item[this.selectedGroup],
136
- value: item[valueKey],
137
- type: valueKey, // 添加一个字段来区分不同的数值列
138
- })
139
- })
140
- })
141
- return transformedData
142
- }
143
- },
144
- }
145
- }
146
- </script>
147
- <style lang="less" scoped>
148
- .chart-card {
149
- height: calc(100vh - 550px);
150
- .chart-content {
151
- width: 500px;
152
- height: 250px;
153
- }
154
- }
155
- </style>
1
+ <template>
2
+ <div class="chart-card">
3
+ <a-row type="flex" align="middle" justify="center" :gutter="16">
4
+ <a-col>
5
+ 分组条件:
6
+ <a-select v-model="selectedGroup" style="width: 200px" @change="updateCharts">
7
+ <a-select-option v-for="option in groupOptions" :key="option" :value="option">{{ option }}</a-select-option>
8
+ </a-select>
9
+ </a-col>
10
+ <a-col>
11
+ 数值列:
12
+ <a-select v-model="selectedValues" mode="multiple" style="width: 200px" @change="updateCharts">
13
+ <a-select-option v-for="option in valueOptions" :key="option" :value="option">{{ option }}</a-select-option>
14
+ </a-select>
15
+ </a-col>
16
+ </a-row>
17
+ <a-divider/>
18
+ <a-row align="middle" justify="space-around" :gutter="24">
19
+ <a-col :span="8">
20
+ <div ref="pieChart" class="chart-content"></div>
21
+ </a-col>
22
+ <a-col :span="8">
23
+ <div ref="columnChart" class="chart-content"></div>
24
+ </a-col>
25
+ <a-col :span="8">
26
+ <div id="lineChart" ref="lineChart" class="chart-content"></div>
27
+ </a-col>
28
+ </a-row>
29
+ </div>
30
+ </template>
31
+
32
+ <script>
33
+ import * as echarts from 'echarts'
34
+
35
+ export default {
36
+ data () {
37
+ return {
38
+ selectedGroup: null,
39
+ groupOptions: [],
40
+ valueOptions: [],
41
+ selectedValues: [], // 更新为数组,支持多选
42
+ pieChart: null,
43
+ columnChart: null,
44
+ lineChart: null,
45
+ intervalId: null,
46
+ componentKey: 0,
47
+ commonOptions: {
48
+ tooltip: {
49
+ trigger: 'item'
50
+ },
51
+ grid: {
52
+ left: '3%',
53
+ right: '4%',
54
+ bottom: '3%',
55
+ containLabel: true
56
+ },
57
+ legend: {},
58
+ color: ['#5DB1FF', '#59D4D4', '#FFD700', '#FF7F50', '#87CEFA',
59
+ '#32CD32', '#DA70D6', '#6495ED', '#DC143C', '#00FFFF',
60
+ '#00008B', '#008B8B', '#B8860B', '#A9A9A9']
61
+ }
62
+ }
63
+ },
64
+ mounted () {
65
+ this.initData()
66
+ // 定时刷新图表
67
+ this.intervalId = setInterval(() => {
68
+ this.renderLineChart()
69
+ }, 3000)
70
+ },
71
+ beforeDestroy () {
72
+ // 组件销毁时清除定时器
73
+ clearInterval(this.intervalId)
74
+ },
75
+ props: {
76
+ rawData: {
77
+ type: Array,
78
+ required: true
79
+ }
80
+ },
81
+ watch: {
82
+ rawData: {
83
+ deep: true,
84
+ handler (newVal) {
85
+ this.initData()
86
+ }
87
+ }
88
+ },
89
+ methods: {
90
+ initData () {
91
+ this.initializeOptions()
92
+ this.selectedGroup = this.groupOptions[0]
93
+ if (this.valueOptions.length > 0) {
94
+ this.selectedValues = [this.valueOptions[0]] // 默认选择第一个数值列
95
+ }
96
+ this.updateCharts()
97
+ },
98
+ initializeOptions () {
99
+ if (this.rawData.length > 0) {
100
+ const firstRow = this.rawData[0]
101
+ this.groupOptions = Object.keys(firstRow).filter(key => typeof firstRow[key] === 'string')
102
+ this.valueOptions = Object.keys(firstRow).filter(key => typeof firstRow[key] === 'number')
103
+ }
104
+ },
105
+ updateCharts () {
106
+ this.renderPieChart()
107
+ this.renderColumnChart()
108
+ this.renderLineChart()
109
+ },
110
+ renderPieChart () {
111
+ const transformedData = this.transformDataForChart('pie')
112
+ const options = {
113
+ series: [
114
+ {
115
+ type: 'pie',
116
+ radius: '50%',
117
+ data: transformedData,
118
+ emphasis: {
119
+ itemStyle: {
120
+ shadowBlur: 10,
121
+ shadowOffsetX: 0,
122
+ shadowColor: 'rgba(0, 0, 0, 0.5)'
123
+ }
124
+ }
125
+ }
126
+ ]
127
+ }
128
+ echarts.init(this.$refs.pieChart).setOption(Object.assign(
129
+ this.commonOptions,
130
+ options
131
+ )
132
+ )
133
+ },
134
+ renderColumnChart () {
135
+ const transformedData = this.transformDataForChart()
136
+ const options = {
137
+ dataset: {
138
+ dimensions: ['category', ...this.selectedValues],
139
+ source: transformedData
140
+ },
141
+ xAxis: { type: 'category' },
142
+ yAxis: {},
143
+ series: this.selectedValues.map(item => {
144
+ return { type: 'bar' }
145
+ })
146
+ }
147
+ echarts.init(this.$refs.columnChart).setOption(Object.assign(
148
+ this.commonOptions,
149
+ options
150
+ ))
151
+ },
152
+ renderLineChart () {
153
+ const transformedData = this.transformDataForChart('line')
154
+ const options = {
155
+ tooltip: {
156
+ trigger: 'axis'
157
+ },
158
+ legend: {
159
+ data: this.selectedValues
160
+ },
161
+ grid: {
162
+ left: '3%',
163
+ right: '4%',
164
+ bottom: '3%',
165
+ containLabel: true
166
+ },
167
+ xAxis: {
168
+ type: 'category',
169
+ boundaryGap: false,
170
+ data: this.rawData.map(item => item.name)
171
+ },
172
+ yAxis: {
173
+ type: 'value'
174
+ },
175
+ series: transformedData,
176
+ animationDuration: 2000
177
+ }
178
+ if (!this.lineChart) {
179
+ this.lineChart = echarts.init(this.$refs.lineChart)
180
+ }
181
+ this.lineChart.clear()
182
+ this.lineChart.setOption(Object.assign(
183
+ this.commonOptions,
184
+ options
185
+ ), true)
186
+ },
187
+ transformDataForChart (type) {
188
+ if (type === 'pie') {
189
+ // 饼图数据转换逻辑:将选中的数值列汇总
190
+ return this.selectedValues.map(valueKey => ({
191
+ name: valueKey,
192
+ value: this.rawData.reduce((sum, item) => sum + item[valueKey], 0),
193
+ }))
194
+ } else if (type === 'line') {
195
+ // 饼图数据转换逻辑:将选中的数值列汇总
196
+ return this.selectedValues.map(valueKey => ({
197
+ name: valueKey,
198
+ type: 'line',
199
+ stack: 'Total',
200
+ data: this.rawData.map(item => item[valueKey]),
201
+ }))
202
+ } else {
203
+ // 柱状图数据转换逻辑:为每个分组条件和选中的数值列创建条目
204
+ const transformedData = []
205
+ this.rawData.forEach(item => {
206
+ const tempData = {
207
+ category: item[this.selectedGroup]
208
+ }
209
+ this.selectedValues.forEach(valueKey => {
210
+ tempData[valueKey] = item[valueKey]
211
+ })
212
+ transformedData.push(tempData)
213
+ })
214
+ return transformedData
215
+ }
216
+ },
217
+ }
218
+ }
219
+ </script>
220
+ <style lang="less" scoped>
221
+ .chart-card {
222
+ .chart-content {
223
+ height: 250px;
224
+ }
225
+ }
226
+ </style>
@@ -1,112 +1,63 @@
1
- <template>
2
- <a-tabs
3
- v-model="activeKey"
4
- type="editable-card"
5
- @edit="onEdit"
6
- hide-add
7
- @change="$emit('tab-change', activeKey)">
8
- <a-tab-pane v-for="pane in panes" :key="pane.key" :closable="pane.closable">
9
- <template slot="tab">
10
- <ellipsis :length="20" tooltip>{{ pane.title }}</ellipsis>
11
- </template>
12
- <div class="data-content">
13
- <!-- <a-button><a-icon type="redo"/>刷新数据</a-button>-->
14
- <a-tabs v-model="dataTypeActiveKey">
15
- <a-tab-pane :key="'0'" tab="表格">
16
- <DynamicTable :table-data="pane.content"></DynamicTable>
17
- </a-tab-pane>
18
- <a-tab-pane :key="'1'" tab="图表">
19
- <div class="chart-card">
20
- <ChartSelector :rawData="pane.content"/>
21
- </div>
22
- </a-tab-pane>
23
- </a-tabs>
24
- <EvaluationArea :uuid="pane.key"/>
25
- </div>
26
- </a-tab-pane>
27
- </a-tabs>
28
- </template>
29
-
30
- <script>
31
- import ChartSelector from './ChartSelector.vue'
32
- import EvaluationArea from './EvaluationArea.vue'
33
- import Ellipsis from '@vue2-client/components/Ellipsis/Ellipsis.vue'
34
- import DynamicTable from './DynamicTable.vue'
35
-
36
- export default {
37
- components: {
38
- DynamicTable,
39
- Ellipsis,
40
- ChartSelector,
41
- EvaluationArea
42
- },
43
- data () {
44
- return {
45
- activeKey: '1',
46
- dataTypeActiveKey: '0',
47
- panes: [],
48
- newTabIndex: 0,
49
- }
50
- },
51
- mounted () {
52
- },
53
- methods: {
54
- onEdit (targetKey, action) {
55
- const activeKey = this[action](targetKey)
56
- if (this.panes.length > 0) {
57
- this.$emit('tab-change', activeKey)
58
- this.$emit('remove-cache', targetKey)
59
- } else {
60
- this.$emit('tab-change', undefined)
61
- }
62
- },
63
- add (obj) {
64
- const { uuid, question, data } = obj
65
- const activeKey = uuid
66
- this.panes.push({ title: question, content: data, key: uuid })
67
- this.activeKey = activeKey
68
- },
69
- remove (targetKey) {
70
- let activeKey = this.activeKey
71
- let lastIndex
72
- this.panes.forEach((pane, i) => {
73
- if (pane.key === targetKey) {
74
- lastIndex = i - 1
75
- }
76
- })
77
- const panes = this.panes.filter(pane => pane.key !== targetKey)
78
- if (panes.length && activeKey === targetKey) {
79
- if (lastIndex >= 0) {
80
- activeKey = panes[lastIndex].key
81
- } else {
82
- activeKey = panes[0].key
83
- }
84
- }
85
- this.panes = panes
86
- this.activeKey = activeKey
87
- return activeKey
88
- },
89
- set (targetKey) {
90
- this.activeKey = targetKey
91
- }
92
- }
93
- }
94
- </script>
95
- <style lang="less" scoped>
96
- .tab-title {
97
- font-size: 20px;
98
- font-weight: bold;
99
- color: #333;
100
- }
101
- .chart-card {
102
- margin-top: 20px;
103
- }
104
- .data-content {
105
- background-color: #fff;
106
- padding: 20px;
107
- border-radius: 8px;
108
- }
109
- :deep(.ant-tabs-bar) {
110
- margin-bottom: 0px;
111
- }
112
- </style>
1
+ <template>
2
+ <a-row class="data-content">
3
+ <a-tabs v-model="dataTypeActiveKey">
4
+ <a-tab-pane :key="'0'" tab="表格">
5
+ <DynamicTable :table-data="pane.content"></DynamicTable>
6
+ </a-tab-pane>
7
+ <a-tab-pane :key="'1'" tab="图表">
8
+ <div class="chart-card">
9
+ <ChartSelector :rawData="pane.content"/>
10
+ </div>
11
+ </a-tab-pane>
12
+ </a-tabs>
13
+ <EvaluationArea :uuid="pane.key" v-if="pane.key"/>
14
+ </a-row>
15
+ </template>
16
+
17
+ <script>
18
+ import ChartSelector from './ChartSelector.vue'
19
+ import EvaluationArea from './EvaluationArea.vue'
20
+ import Ellipsis from '@vue2-client/components/Ellipsis/Ellipsis.vue'
21
+ import DynamicTable from './DynamicTable.vue'
22
+
23
+ export default {
24
+ components: {
25
+ DynamicTable,
26
+ Ellipsis,
27
+ ChartSelector,
28
+ EvaluationArea
29
+ },
30
+ data () {
31
+ return {
32
+ dataTypeActiveKey: '0',
33
+ pane: {}
34
+ }
35
+ },
36
+ mounted () {
37
+ },
38
+ methods: {
39
+ show (obj) {
40
+ const { uuid, question, data } = obj
41
+ this.pane = { title: question, content: data, key: uuid }
42
+ },
43
+ }
44
+ }
45
+ </script>
46
+ <style lang="less" scoped>
47
+ .tab-title {
48
+ font-size: 20px;
49
+ font-weight: bold;
50
+ color: #333;
51
+ }
52
+ .chart-card {
53
+ margin-top: 20px;
54
+ }
55
+ .data-content {
56
+ background-color: #fff;
57
+ padding: 20px;
58
+ border-radius: 8px;
59
+ }
60
+ :deep(.ant-tabs-bar) {
61
+ margin-bottom: 0px;
62
+ }
63
+ </style>