整合前端
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<div class="express-question-list">
|
||||
<MiniList :list="questionList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listExpressQuestion } from '@/api/oa/expressQuestion';
|
||||
import MiniList from '@/components/HomeModules/components/MiniList.vue';
|
||||
|
||||
export default {
|
||||
name: 'ExpressQuestionList',
|
||||
components: { MiniList },
|
||||
data() {
|
||||
return {
|
||||
questionList: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchQuestions();
|
||||
},
|
||||
methods: {
|
||||
async fetchQuestions() {
|
||||
try {
|
||||
const res = await listExpressQuestion({ pageNum: 1, pageSize: 10 });
|
||||
console.log(res, 'ExpressQuestionList fetchQuestions response');
|
||||
// 假设res.rows为问题数组,字段有questionTitle、createTime
|
||||
this.questionList = (res.rows || res.data || []).map(item => ({
|
||||
title: item.expressCode || item.questionId || '无标题',
|
||||
date: item.reportTime || '',
|
||||
id: item.questionId || Math.random().toString(36).substr(2, 9) // 使用随机字符串作为ID
|
||||
}));
|
||||
} catch (e) {
|
||||
this.questionList = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.express-question-list {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
43
ruoyi-ui/src/components/HomeModules/modules/FeedbackList.vue
Normal file
43
ruoyi-ui/src/components/HomeModules/modules/FeedbackList.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div class="feedback-list">
|
||||
<MiniList :list="feedbackList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listFeedback } from '@/api/oa/feedback';
|
||||
import MiniList from '@/components/HomeModules/components/MiniList.vue';
|
||||
|
||||
export default {
|
||||
name: 'FeedbackList',
|
||||
components: { MiniList },
|
||||
data() {
|
||||
return {
|
||||
feedbackList: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchFeedbacks();
|
||||
},
|
||||
methods: {
|
||||
async fetchFeedbacks() {
|
||||
try {
|
||||
const res = await listFeedback({ pageNum: 1, pageSize: 10 });
|
||||
this.feedbackList = (res.rows || res.data || []).map(item => ({
|
||||
title: item.title || '无标题',
|
||||
date: item.createTime || item.updateTime || '',
|
||||
id: item.feedbackId
|
||||
}));
|
||||
} catch (e) {
|
||||
this.feedbackList = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.feedback-list {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
237
ruoyi-ui/src/components/HomeModules/modules/FinancialCharts.vue
Normal file
237
ruoyi-ui/src/components/HomeModules/modules/FinancialCharts.vue
Normal file
@@ -0,0 +1,237 @@
|
||||
<template>
|
||||
<el-card>
|
||||
<!-- <h2>财务分析</h2>-->
|
||||
<!-- <div style="display: flex; justify-content: space-between;">-->
|
||||
<!-- <!– 月度收入与支出对比柱状图 –>-->
|
||||
<!-- <div id="bar-chart" style="height: 400px;width: 50%;"></div>-->
|
||||
|
||||
<!-- <!– 年度费用分类占比饼图 –>-->
|
||||
<!-- <div id="pie-chart" style="height: 400px; width: 48%; margin-top: 20px;"></div>-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!-- 项目活跃度堆叠条形图 -->
|
||||
<div
|
||||
id="activity-chart"
|
||||
ref="activityChart"
|
||||
style="width: 100%; height: 450px; margin-top: 20px"
|
||||
></div>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { barData } from "@/api/oa/finance";
|
||||
import { projectData, projectDataByMonthAndDate } from "@/api/oa/project";
|
||||
import * as echarts from "echarts";
|
||||
|
||||
export default {
|
||||
name: "FinancialCharts",
|
||||
data() {
|
||||
return {
|
||||
// 示例数据:每个项目在不同日期的进度
|
||||
activityData: [],
|
||||
queryFinanceParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 9999,
|
||||
financeType: "0",
|
||||
projectId: 0,
|
||||
},
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.currentBlurList();
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 最近六个月核算情况,如果显示更多月份,请修改控制器:int[] integers = {0,1, 2, 3, 4, 5};
|
||||
*/
|
||||
currentBlurList() {
|
||||
barData(this.queryFinanceParams).then((response) => {
|
||||
this.currentList = response.data;
|
||||
projectData(new Date()).then((res) => {
|
||||
this.projectList = res.data;
|
||||
// 获取活动图数据
|
||||
projectDataByMonthAndDate().then((res) => {
|
||||
this.projects = res.data;
|
||||
this.drawActivityChart(); // 绘制项目活跃度堆叠条形图
|
||||
// 获取条形图数据
|
||||
// this.initCharts();
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
// 初始化财务图表
|
||||
initCharts() {
|
||||
// 1. 获取 ECharts 实例
|
||||
const barChart = echarts.init(document.getElementById("bar-chart"));
|
||||
|
||||
// 2. 从 currentList 中提取数据
|
||||
const months = this.currentList.map((item) => item.month); // x轴
|
||||
const financeOut = this.currentList.map((item) => item.totalOut); // 支出
|
||||
const financeIn = this.currentList.map((item) => item.totalIn); // 收入
|
||||
|
||||
// 3. 配置 ECharts 选项
|
||||
const barOption = {
|
||||
title: {
|
||||
text: "月度收入与支出对比",
|
||||
left: "center",
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: months,
|
||||
axisLabel: {
|
||||
rotate: 45, // X轴标签倾斜 45 度
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
axisLabel: {
|
||||
// 若想带单位或自定义格式可写 formatter: '{value} 元' 等
|
||||
formatter: "{value}",
|
||||
rotate: 60, // Y轴标签倾斜 60 度
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "支出",
|
||||
type: "bar",
|
||||
data: financeOut,
|
||||
color: "#91CC75",
|
||||
},
|
||||
{
|
||||
name: "收入",
|
||||
type: "bar",
|
||||
data: financeIn,
|
||||
color: "#5470C6",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// 4. 渲染图表
|
||||
barChart.setOption(barOption);
|
||||
|
||||
// 1. 获取/初始化 ECharts 实例
|
||||
const pieChart = echarts.init(document.getElementById("pie-chart"));
|
||||
|
||||
// 2. 处理项目列表数据
|
||||
// - 过滤掉 totalPrice <= 0 的
|
||||
// - 映射成 ECharts 饼图需要的格式 { name, value, itemStyle: { color } }
|
||||
const detailList = this.projectList
|
||||
.filter((item) => parseFloat(item.totalPrice) > 0)
|
||||
.map((item) => ({
|
||||
name: item.projectName || "未命名",
|
||||
value: parseFloat(item.totalPrice),
|
||||
// ECharts 支持对每个扇区单独指定颜色
|
||||
itemStyle: {
|
||||
color: item.color || "#ccc", // 如果 color 未定义,备用 '#ccc'
|
||||
},
|
||||
}));
|
||||
|
||||
// 3. 构建一个带逗号的数字格式化工具
|
||||
const numberFormatter = new Intl.NumberFormat("zh-CN");
|
||||
|
||||
// 4. 配置 ECharts
|
||||
const pieOption = {
|
||||
title: {
|
||||
text: "当月项目支出占比",
|
||||
left: "center",
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
// 自定义 tooltip 显示:{项目名称}:{格式化数值}元 ({百分比}%)
|
||||
formatter: function (params) {
|
||||
const valStr = numberFormatter.format(params.value);
|
||||
return `${params.seriesName}<br/>${params.name}:${valStr}元 (${params.percent}%)`;
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "项目支出",
|
||||
type: "pie",
|
||||
radius: "50%",
|
||||
data: detailList,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// 5. 渲染图表
|
||||
pieChart.setOption(pieOption);
|
||||
},
|
||||
|
||||
// 绘制项目活跃度堆叠条形图
|
||||
drawActivityChart() {
|
||||
const chart = echarts.init(this.$refs.activityChart);
|
||||
|
||||
// 处理数据:转化为堆叠条形图所需的格式
|
||||
const dates = [
|
||||
...new Set(
|
||||
this.projects.map((item) => item.createTime.substring(0, 10))
|
||||
),
|
||||
].sort(); // 获取所有日期
|
||||
const projects = [
|
||||
...new Set(this.projects.map((item) => item.projectName)),
|
||||
]; // 获取所有项目
|
||||
|
||||
// 创建数据系列:每个项目一个系列,颜色使用项目的 color 属性
|
||||
const series = projects.map((projectName) => {
|
||||
const projectColor =
|
||||
this.projects.find((item) => item.projectName === projectName)
|
||||
?.color || "#000"; // 默认黑色
|
||||
return {
|
||||
name: projectName,
|
||||
type: "bar",
|
||||
stack: "total",
|
||||
data: dates.map((date) => {
|
||||
const progress = this.projects.find(
|
||||
(item) =>
|
||||
item.projectName === projectName &&
|
||||
item.createTime.substring(0, 10) === date
|
||||
);
|
||||
return progress ? progress.laborCost : 0;
|
||||
}),
|
||||
itemStyle: {
|
||||
color: projectColor, // 使用项目的颜色
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
// 配置项
|
||||
const option = {
|
||||
title: {
|
||||
text: "项目活跃度",
|
||||
subtext: "显示每个项目的参与进度",
|
||||
top: 0,
|
||||
},
|
||||
grid: {
|
||||
top: "20%", // 设置 grid 上部距离,确保有空间放置 title
|
||||
bottom: "30%", // 保证底部有足够空间放置 legend
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: { type: "shadow" },
|
||||
},
|
||||
legend: {
|
||||
align: "left", // 对齐方式
|
||||
itemWidth: 10, // 图例标记的宽度
|
||||
itemHeight: 20, // 图例标记的高度
|
||||
data: projects,
|
||||
bottom: 0,
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: dates,
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
},
|
||||
series: series,
|
||||
};
|
||||
|
||||
// 使用配置项
|
||||
chart.setOption(option);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
46
ruoyi-ui/src/components/HomeModules/modules/MyTaskList.vue
Normal file
46
ruoyi-ui/src/components/HomeModules/modules/MyTaskList.vue
Normal file
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<div class="my-task-list">
|
||||
<MiniList :list="taskList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 这个组件是我创建的任务
|
||||
import { listTaskCreate } from '@/api/oa/task';
|
||||
import MiniList from '@/components/HomeModules/components/MiniList.vue';
|
||||
|
||||
export default {
|
||||
name: 'MyTaskList',
|
||||
components: { MiniList },
|
||||
data() {
|
||||
return {
|
||||
taskList: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchTasks();
|
||||
},
|
||||
methods: {
|
||||
async fetchTasks() {
|
||||
try {
|
||||
const res = await listTaskCreate({ pageNum: 1, pageSize: 50 });
|
||||
// 假设res.rows为任务数组,字段有taskTitle、createTime
|
||||
this.taskList = (res.rows || res.data || []).map(item => ({
|
||||
title: item.taskTitle || item.title || '无标题',
|
||||
extra: item.workerNickName || '',
|
||||
date: item.createTime || item.endTime || '',
|
||||
id: item.id || item.taskId || item.key || Math.random()
|
||||
}));
|
||||
} catch (e) {
|
||||
this.taskList = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.my-task-list {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<div class="my-task-list">
|
||||
<MiniList :list="taskList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 这个组件是分配给我的任务
|
||||
import { listTaskWork } from '@/api/oa/task';
|
||||
import MiniList from '@/components/HomeModules/components/MiniList.vue';
|
||||
|
||||
export default {
|
||||
name: 'MyTaskList',
|
||||
components: { MiniList },
|
||||
data() {
|
||||
return {
|
||||
taskList: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchTasks();
|
||||
},
|
||||
methods: {
|
||||
async fetchTasks() {
|
||||
try {
|
||||
const res = await listTaskWork({ pageNum: 1, pageSize: 50 });
|
||||
// 假设res.rows为任务数组,字段有taskTitle、createTime
|
||||
this.taskList = (res.rows || res.data || []).map(item => ({
|
||||
title: item.taskTitle || item.title || '无标题',
|
||||
extra: item.createUserNickName || '',
|
||||
date: item.createTime || item.endTime || '',
|
||||
id: item.id || item.taskId || item.key || Math.random()
|
||||
}));
|
||||
} catch (e) {
|
||||
this.taskList = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.my-task-list {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="overdue-projects">
|
||||
<!-- 标题和刷新按钮容器 -->
|
||||
<div class="title-container">
|
||||
<h3>逾期项目</h3>
|
||||
<button class="refresh-btn" @click="getList">
|
||||
刷新
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 使用MiniList组件展示项目列表 -->
|
||||
<MiniList
|
||||
:list="formattedProjects"
|
||||
:page-size="10"
|
||||
:highlight-condition="isHighAmount"
|
||||
@row-click="handleRowClick"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listProject } from "@/api/oa/project";
|
||||
import MiniList from "../components/MiniList.vue"; // 引入MiniList组件
|
||||
|
||||
export default {
|
||||
name: "ProjectManagement",
|
||||
components: {
|
||||
MiniList // 注册组件
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
projects: [], // 原始项目数据
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 999, // 一次性获取所有数据,前端分页
|
||||
projectStatus: 0
|
||||
},
|
||||
loading: true
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// 格式化项目数据适配MiniList组件
|
||||
formattedProjects() {
|
||||
return this.projects.map(project => ({
|
||||
id: project.id,
|
||||
projectId: project.projectId, // 保留项目ID用于跳转
|
||||
title: `项目名称:${project.projectName}`, // 标题显示项目名称
|
||||
extra: `金额:${project.funds}`, // 额外信息显示金额
|
||||
date: `逾期天数:${-project.remainTime}`, // 日期区域显示逾期天数
|
||||
funds: project.funds // 保留金额用于高亮判断
|
||||
}));
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 查询项目管理列表 */
|
||||
getList () {
|
||||
this.loading = true;
|
||||
listProject(this.queryParams).then((response) => {
|
||||
// 过滤逾期项目并按金额从大到小排序
|
||||
this.projects = response.rows
|
||||
.filter(item => item.remainTime <= 0)
|
||||
.sort((a, b) => b.funds - a.funds);
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
|
||||
// 高亮条件:金额超过50万
|
||||
isHighAmount(item) {
|
||||
return item.funds > 500000;
|
||||
},
|
||||
|
||||
// 处理列表项点击事件(跳转详情页)
|
||||
handleRowClick(item) {
|
||||
this.$router.push({
|
||||
path: `/project/project?projectId=${item.projectId}`
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 标题和刷新按钮容器样式 */
|
||||
.title-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
/* 刷新按钮样式 */
|
||||
.refresh-btn {
|
||||
padding: 5px 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.refresh-btn:hover {
|
||||
background-color: #f5f5f5;
|
||||
border-color: #ccc;
|
||||
}
|
||||
|
||||
/* 适配MiniList的样式补充 */
|
||||
|
||||
/* 确保序号样式与原有保持一致 */
|
||||
::v-deep .mini-list .mini-list-index {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div class="requirement-list">
|
||||
<MiniList :list="requirementList" :pageSize="7" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { listRequirements } from '@/api/oa/requirement';
|
||||
import MiniList from '@/components/HomeModules/components/MiniList.vue';
|
||||
|
||||
export default {
|
||||
name: 'RequirementList',
|
||||
components: { MiniList },
|
||||
data() {
|
||||
return {
|
||||
requirementList: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchRequirements();
|
||||
},
|
||||
methods: {
|
||||
async fetchRequirements() {
|
||||
try {
|
||||
const res = await listRequirements({ pageNum: 1, pageSize: 50 });
|
||||
this.requirementList = (res.rows || res.data || []).map(item => ({
|
||||
title: item.title || item.requirementTitle || '无标题',
|
||||
date: item.createTime || item.updateTime || '',
|
||||
id: item.id || item.requirementId || item.key || Math.random()
|
||||
}));
|
||||
} catch (e) {
|
||||
this.requirementList = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.requirement-list {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user