123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523 |
- <template>
- <div>
- <a-button @click="refreshData" type="primary" style="margin: 15px 30px 15px 15px;">重 置</a-button>
- <a-dropdown-button @click="handleButtonClick">
- {{belongPark}}
- <template #overlay>
- <a-menu @click="handleMenuClick">
- <a-menu-item key="1">
- <UserOutlined />
- 总公司园区
- </a-menu-item>
-
- <a-menu-item key="2">
- <UserOutlined />
- 西区
- </a-menu-item>
-
- <a-menu-item key="3">
- <UserOutlined />
- 电厂
- </a-menu-item>
-
- <a-menu-item key="4">
- <UserOutlined />
- 东区
- </a-menu-item>
-
- <a-menu-item key="5">
- <UserOutlined />
- 高青
- </a-menu-item>
-
- <a-menu-item key="6">
- <UserOutlined />
- 制衣
- </a-menu-item>
- </a-menu>
- </template>
- <template #icon><down-outlined /></template>
- </a-dropdown-button>
- <span style="margin: 15px 60px 15px 15px;"> 共计 {{dataSize}} 条数据</span>
- <a-button type="primary" @click="showStatisticsPanel" style="margin: 15px 30px 15px 250px;" :disabled='true'>展开数据统计面板(暂未开放)</a-button>
- <div class="dataAnalysis" v-show="isshowPanel">
- <div class="panelItem" id="adviceNum" style="width: 28%;"></div>
- <div class="panelItem" id="adviceNumYear" style="width: 40%;"></div>
- <div class="panelItem" id="adviceNumBread" style="width: 28%;"></div>
- </div>
- <a-table
- :columns="columns"
- :data-source="dataSource"
- :row-selection="rowSelection" bordered>
- <template #bodyCell="{ column, text, record }">
- <template v-if="['advice'].includes(column.dataIndex)">
- <div class="adviceBox">
- <span style="font-size: 1rem">{{ text }}</span>
- <br /><br />
- <span>{{record.type}}园区 - {{record.createTime}}</span>
- </div>
- </template>
- <template v-else-if="column.dataIndex === 'image'">
- <div class="image-container">
- <a-image
- v-if="record.urlList!=0"
- v-for="(filename, index) in record.urlList"
- :width="120"
- :height="120"
- :src="`${imageBaseUrl}${filename}`"/>
- </div>
- </template>
- <template v-else-if="column.dataIndex === 'reply'">
- <a-textarea :rows="4"/>
- <a-button type="primary" style="float: right">回 复</a-button>
- </template>
- <template v-else-if="column.dataIndex === 'edit'">
- <a-popconfirm
- title="你确定要删除这条信息吗?"
- ok-text="是"
- cancel-text="否"
- @confirm="deleteAdviceInfo(record.key)"
- @cancel="cancel">
- <a-button type="link">删 除</a-button>
- </a-popconfirm>
- </template>
- </template>
- </a-table>
- </div>
- </template>
- <script lang="ts" setup>
- import { cloneDeep } from 'lodash-es';
- import { reactive, ref, onMounted} from 'vue';
- import type { UnwrapRef } from 'vue';
- import axios from 'axios';
- import {Image} from "ant-design-vue";
- import type { MenuProps } from 'ant-design-vue';
- import { DownOutlined } from '@ant-design/icons-vue';
- import {baseUrl, imageBaseUrl} from '@/config.js'
- import * as echarts from 'echarts';
- interface DataItem {
- key: string;
- advice: string;
- urlList: any;
- createTime: string;
- type: string
- }
- const columns = [
- {
- title: '意见及建议',
- dataIndex: 'advice',
- width: '20%',
- },
- {
- title: '图片',
- dataIndex: 'image',
- width: '40%',
- },
- {
- title: '回复',
- dataIndex: 'reply',
- width: '20%',
- },
- {
- title: '操作',
- dataIndex: 'edit',
- width: '15%'
- }
- ];
- const editableData: UnwrapRef<Record<string, DataItem>> = reactive({});
- let dataSource = ref()
- let data: DataItem[] = [];
- let dataSize = 0
- const edit = (key: string) => {
- editableData[key] = cloneDeep(dataSource.value.filter(item => key === item.key)[0]);
- };
- const save = (key: string) => {
- Object.assign(dataSource.value.filter(item => key === item.key)[0], editableData[key]);
- delete editableData[key];
- };
- const cancel = (key: string) => {
- delete editableData[key];
- };
- const handleButtonClick = (e: Event) => {
- console.log('click left button', e);
- };
- const belongPark = ref('全部园区')
- const type = ref('')
- const handleMenuClick: MenuProps['onClick'] = e => {
- console.log('click', e.key);
- switch(e.key){
- case '1':
- belongPark.value = '总公司园区';
- type.value = '1'
- break;
- case '2':
- belongPark.value = '西区';
- type.value = '2'
- break;
- case '3':
- belongPark.value = '电厂';
- type.value = '3'
- break;
- case '4':
- belongPark.value = '东区';
- type.value = '4'
- break;
- case '5':
- belongPark.value = '高青';
- type.value = '5'
- break;
- case '6':
- belongPark.value = '制衣';
- type.value = '6'
- break;
- }
- mygetData()
- };
- const rowSelection = ref({
- checkStrictly: false,
- onChange: (selectedRowKeys: (string | number)[], selectedRows: DataItem[]) => {
- console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
- },
- onSelect: (record: DataItem, selected: boolean, selectedRows: DataItem[]) => {
- console.log(record, selected, selectedRows);
- },
- onSelectAll: (selected: boolean, selectedRows: DataItem[], changeRows: DataItem[]) => {
- console.log(selected, selectedRows, changeRows);
- },
- });
- async function mygetData(){
- try {
- // 查询前清空数据
- data = []
- const response = await axios.get(baseUrl+'/queryReview?type='+type.value);
- dataSize = response.data.length
- for (let item of response.data){
- const urlList = item.imageInfoList.trim().split(/\s*,\s*/)
- switch(item.type){
- case '1':
- item.type = '总公司'
- break;
- case '2':
- item.type = '西区'
- break;
- case '3':
- item.type = '电厂'
- break;
- case '4':
- item.type = '东区'
- break;
- case '5':
- item.type = '高青'
- break;
- case '6':
- item.type = '制衣'
- break;
- }
- data.push({
- key: item.id,
- advice: item.advice,
- urlList: urlList,
- createTime: item.createTime,
- type: item.type
- })
- }
- dataSource.value = data;
- } catch (error) {
- console.error('Error fetching data:', error);
- }
- };
- function refreshData(){
- belongPark.value = '全部园区'
- type.value = ''
- data = []
- mygetData()
- };
- async function deleteAdviceInfo(key:string){
- await axios.get(baseUrl+'/deleteAdviceInfo',{params: {"id":key}})
- .then(response =>{
- // 删除成功后,刷新页面
- dataSource.value = dataSource.value.filter(item => item.key !== key);
- }).catch(error => {
- console.error('删除失败:', error);
- });
- };
- const isshowPanel = ref(false)
- function showStatisticsPanel(){
- console.log("展示面板")
- isshowPanel.value = !isshowPanel.value
-
- setTimeout(()=>{
- if(isshowPanel.value){
- // 数据可视化区域
- // 月度
- var chartDom = document.getElementById('adviceNum');
- var myChart = echarts.init(chartDom);
- var option;
-
- option = {
- title: {
- text: '本月各园区意见征集数量统计',
- textStyle: {
- fontSize: '20px',
- color: '#333',
- top: "10%"
- }
- },
- grid: {
- height:"70%",
- width: "80%",
- top: "22%"
- },
- xAxis: {
- type: 'category',
- data: ['总公司园区', '西区', '电厂', '东区', '高青', '制衣'],
- axisLabel: {
- interval: 0 // 强制显示所有标签
- }
- },
- yAxis: {
- type: 'value',
- min: 0,
- max: 50,
- interval: 5,
- },
- series: [
- {
- data: [
- {
- value: 35,
- itemStyle: {
- color: '#a90000'
- }
- },
- 20,
- 15,
- 8,
- 7,
- 11,
- 13
- ],
- type: 'bar'
- }
- ]
- };
-
- option && myChart.setOption(option);
-
- //年度
- var chartDom2 = document.getElementById('adviceNumYear');
- var myChart2 = echarts.init(chartDom2);
- var option2;
-
- option2 = {
- title: {
- text: '各园区年度统计'
- },
- tooltip: {
- trigger: 'axis'
- },
- legend: {
- data: ['总公司', '西区', '电厂', '东区', '高青', '制衣']
- },
- grid: {
- left: '3%',
- right: '4%',
- bottom: '3%',
- containLabel: true,
- width: '90%'
- },
- toolbox: {
- feature: {
- saveAsImage: {}
- }
- },
- xAxis: {
- type: 'category',
- boundaryGap: false,
- data: ['一月', '二月', '三月', '四月', '五月', '六月', '七月','八月', '九月','十月','十一月','十二月']
- },
- yAxis: {
- type: 'value'
- },
- series: [
- {
- name: '总公司',
- type: 'line',
- stack: 'Total',
- data: [120, 132, 101, 134, 90, 230, 210]
- },
- {
- name: '西区',
- type: 'line',
- stack: 'Total',
- data: [220, 182, 191, 234, 290, 330, 310]
- },
- {
- name: '电厂',
- type: 'line',
- stack: 'Total',
- data: [150, 232, 201, 154, 190, 330, 410]
- },
- {
- name: '东区',
- type: 'line',
- stack: 'Total',
- data: [320, 332, 301, 334, 390, 330, 320]
- },
- {
- name: '高青',
- type: 'line',
- stack: 'Total',
- data: [820, 932, 901, 934, 1290, 1330, 1320]
- },
- {
- name: '制衣',
- type: 'line',
- stack: 'Total',
- data: [720, 732, 801, 234, 190, 1330, 1320]
- }
- ]
- };
-
- option2 && myChart2.setOption(option2);
-
- // 饼图
- var chartDom3 = document.getElementById('adviceNumBread');
- var myChart3 = echarts.init(chartDom3);
- var option3;
-
- option3 = {
- grid: {
- left: '3%',
- right: '4%',
- bottom: '3%',
- width: '90%',
- height: '90%'
- },
- title: {
- text: '占比情况统计',
- subtext: 'Fake Data',
- left: 'center'
- },
- tooltip: {
- trigger: 'item'
- },
- legend: {
- orient: 'vertical',
- left: 'left'
- },
- series: [
- {
- name: 'Access From',
- type: 'pie',
- radius: '50%',
- data: [
- { value: 148, name: '总公司' },
- { value: 75, name: '西区' },
- { value: 50, name: '电厂' },
- { value: 44, name: '东区' },
- { value: 30, name: '高青' },
- { value: 66, name: '制衣' }
- ],
- emphasis: {
- itemStyle: {
- shadowBlur: 10,
- shadowOffsetX: 0,
- shadowColor: 'rgba(0, 0, 0, 0.5)'
- }
- }
- }
- ]
- };
-
- option3 && myChart3.setOption(option3);
- }
- },1000)
- }
- onMounted(()=>{
- document.title = '膳食科意见征集后台管理系统'
- const now = Date.now();
- const expirationTime = parseInt(localStorage.getItem('hasPassedPasswordCheck_expiration'));
- const pass = localStorage.getItem('hasPassedPasswordCheck')
- if(pass && !(expirationTime && now > expirationTime)){
- mygetData()
- }else{
- // 数据已过期,从localStorage中移除
- localStorage.removeItem('hasPassedPasswordCheck');
- localStorage.removeItem('hasPassedPasswordCheck_expiration');
- uni.reLaunch({
- url: './checkPassword'
- });
- }
- })
-
- </script>
- <style scoped>
- .adviceBox {
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- width: 100%;
- height: auto;
- max-height: 20vh;
- overflow-y: auto;
- padding: 0.5rem;
- box-sizing: border-box;
- }
- .adviceBox span:first-child {
- text-indent: 2em; /* 首行缩进两格 */
- white-space: pre-line; /* 保留换行符和空格 */
- font-size: 1rem; /* 文字大小 */
- flex-grow: 1; /* 占据剩余空间,确保createTime位于底部 */
- }
- .adviceBox span:last-child {
- align-self: flex-end; /* 将createTime定位至右下角 */
- }
- .ant-upload-select-picture-card i {
- font-size: 32px;
- color: #999;
- }
- .ant-upload-select-picture-card .ant-upload-text {
- margin-top: 8px;
- color: #666;
- }
- .editable-row-operations a {
- margin-right: 8px;
- }
- .image-container {
- display: flex;
- flex-wrap: wrap;
- gap: 20px; /* 图片之间的间距 */
- }
- .dataAnalysis{
- width: 100%;
- height: 40vh;
- display: flex;
- justify-content: space-around;
- }
- .panelItem{
- margin-top: 1vh;
- height: 90%;
- background-color: azure;
- }
- </style>
|