整合前端

This commit is contained in:
砂糖
2026-04-13 17:04:38 +08:00
parent 69609a2cb1
commit 5d4794c9bd
915 changed files with 144259 additions and 0 deletions

View File

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

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

View File

@@ -0,0 +1,237 @@
<template>
<el-card>
<!-- <h2>财务分析</h2>-->
<!-- <div style="display: flex; justify-content: space-between;">-->
<!-- &lt;!&ndash; 月度收入与支出对比柱状图 &ndash;&gt;-->
<!-- <div id="bar-chart" style="height: 400px;width: 50%;"></div>-->
<!-- &lt;!&ndash; 年度费用分类占比饼图 &ndash;&gt;-->
<!-- <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>

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

View File

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

View File

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

View File

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