diff --git a/web-api/src/main/java/com/jeesite/modules/biz/dao/BizCalendarScheduleDao.java b/web-api/src/main/java/com/jeesite/modules/biz/dao/BizCalendarScheduleDao.java new file mode 100644 index 00000000..55038d14 --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/dao/BizCalendarScheduleDao.java @@ -0,0 +1,15 @@ +package com.jeesite.modules.biz.dao; + +import com.jeesite.common.dao.CrudDao; +import com.jeesite.common.mybatis.annotation.MyBatisDao; +import com.jeesite.modules.biz.entity.BizCalendarSchedule; + +/** + * 日程信息DAO接口 + * @author gaoxq + * @version 2025-12-10 + */ +@MyBatisDao(dataSourceName="work") +public interface BizCalendarScheduleDao extends CrudDao { + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/entity/BizCalendarSchedule.java b/web-api/src/main/java/com/jeesite/modules/biz/entity/BizCalendarSchedule.java new file mode 100644 index 00000000..22d6a77b --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/entity/BizCalendarSchedule.java @@ -0,0 +1,115 @@ +package com.jeesite.modules.biz.entity; + +import java.io.Serializable; +import java.util.Date; + +import com.jeesite.common.mybatis.annotation.JoinTable; +import com.jeesite.common.mybatis.annotation.JoinTable.Type; +import com.fasterxml.jackson.annotation.JsonFormat; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import jakarta.validation.constraints.NotNull; + +import com.jeesite.common.entity.DataEntity; +import com.jeesite.common.mybatis.annotation.Column; +import com.jeesite.common.mybatis.annotation.Table; +import com.jeesite.common.mybatis.mapper.query.QueryType; +import com.jeesite.common.utils.excel.annotation.ExcelField; +import com.jeesite.common.utils.excel.annotation.ExcelField.Align; +import com.jeesite.common.utils.excel.annotation.ExcelFields; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; + +/** + * 日程信息Entity + * + * @author gaoxq + * @version 2025-12-10 + */ +@EqualsAndHashCode(callSuper = true) +@Table(name = "biz_calendar_schedule", alias = "a", label = "日程信息信息", columns = { + @Column(name = "create_time", attrName = "createTime", label = "记录时间", isUpdate = false, isUpdateForce = true), + @Column(name = "schedule_id", attrName = "scheduleId", label = "主键标识", isPK = true), + @Column(name = "schedule_no", attrName = "scheduleNo", label = "日程编号"), + @Column(name = "title", attrName = "title", label = "日程标题", queryType = QueryType.LIKE), + @Column(name = "content", attrName = "content", label = "日程详情/备注", isQuery = false), + @Column(name = "start_time", attrName = "startTime", label = "日程开始时间", isQuery = false), + @Column(name = "end_time", attrName = "endTime", label = "日程结束时间", isQuery = false), + @Column(name = "all_day", attrName = "allDay", label = "是否全天"), + @Column(name = "location", attrName = "location", label = "日程地点", isQuery = false), + @Column(name = "priority", attrName = "priority", label = "优先等级"), + @Column(name = "ustatus", attrName = "ustatus", label = "日程状态"), + @Column(name = "remind_time", attrName = "remindTime", label = "提醒时间", isQuery = false, isUpdateForce = true), + @Column(name = "creator_user", attrName = "creatorUser", label = "创建人账号", isUpdate = false, isUpdateForce = true), + @Column(name = "participant_user", attrName = "participantUser", label = "接收人账号"), + @Column(name = "participant_name", attrName = "participantName", label = "接收人名称"), + @Column(name = "update_time", attrName = "updateTime", label = "更新时间", isQuery = false, isUpdateForce = true), +}, orderBy = "a.schedule_id DESC" +) +@Data +public class BizCalendarSchedule extends DataEntity implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + private Date createTime; // 记录时间 + private String scheduleId; // 主键标识 + private String scheduleNo; // 日程编号 + private String title; // 日程标题 + private String content; // 日程详情/备注 + private Date startTime; // 日程开始时间 + private Date endTime; // 日程结束时间 + private String allDay; // 是否全天 + private String location; // 日程地点 + private String priority; // 优先等级 + private String ustatus; // 日程状态 + private Date remindTime; // 提醒时间 + private String creatorUser; // 创建人账号 + private String participantUser; // 接收人账号 + private String participantName; // 接收人名称 + private Date updateTime; // 更新时间 + + @ExcelFields({ + @ExcelField(title = "记录时间", attrName = "createTime", align = Align.CENTER, sort = 10, dataFormat = "yyyy-MM-dd hh:mm"), + @ExcelField(title = "主键标识", attrName = "scheduleId", align = Align.CENTER, sort = 20), + @ExcelField(title = "日程编号", attrName = "scheduleNo", align = Align.CENTER, sort = 30), + @ExcelField(title = "日程标题", attrName = "title", align = Align.CENTER, sort = 40), + @ExcelField(title = "日程详情/备注", attrName = "content", align = Align.CENTER, sort = 50), + @ExcelField(title = "日程开始时间", attrName = "startTime", align = Align.CENTER, sort = 60, dataFormat = "yyyy-MM-dd hh:mm"), + @ExcelField(title = "日程结束时间", attrName = "endTime", align = Align.CENTER, sort = 70, dataFormat = "yyyy-MM-dd hh:mm"), + @ExcelField(title = "是否全天", attrName = "allDay", align = Align.CENTER, sort = 80), + @ExcelField(title = "日程地点", attrName = "location", align = Align.CENTER, sort = 90), + @ExcelField(title = "优先等级", attrName = "priority", dictType = "priority", align = Align.CENTER, sort = 100), + @ExcelField(title = "日程状态", attrName = "ustatus", dictType = "todo_status", align = Align.CENTER, sort = 110), + @ExcelField(title = "提醒时间", attrName = "remindTime", align = Align.CENTER, sort = 120, dataFormat = "yyyy-MM-dd hh:mm"), + @ExcelField(title = "创建人账号", attrName = "creatorUser", align = Align.CENTER, sort = 130), + @ExcelField(title = "接收人账号", attrName = "participantUser", align = Align.CENTER, sort = 150), + @ExcelField(title = "接收人名称", attrName = "participantName", align = Align.CENTER, sort = 160), + @ExcelField(title = "更新时间", attrName = "updateTime", align = Align.CENTER, sort = 170, dataFormat = "yyyy-MM-dd hh:mm"), + }) + public BizCalendarSchedule() { + this(null); + } + + public BizCalendarSchedule(String id) { + super(id); + } + + public Date getCreateTime_gte() { + return sqlMap.getWhere().getValue("create_time", QueryType.GTE); + } + + public void setCreateTime_gte(Date createTime) { + sqlMap.getWhere().and("create_time", QueryType.GTE, createTime); + } + + public Date getCreateTime_lte() { + return sqlMap.getWhere().getValue("create_time", QueryType.LTE); + } + + public void setCreateTime_lte(Date createTime) { + sqlMap.getWhere().and("create_time", QueryType.LTE, createTime); + } + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/service/BizCalendarScheduleService.java b/web-api/src/main/java/com/jeesite/modules/biz/service/BizCalendarScheduleService.java new file mode 100644 index 00000000..abeea54d --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/service/BizCalendarScheduleService.java @@ -0,0 +1,134 @@ +package com.jeesite.modules.biz.service; + +import java.util.List; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.jeesite.common.entity.Page; +import com.jeesite.common.service.CrudService; +import com.jeesite.modules.biz.entity.BizCalendarSchedule; +import com.jeesite.modules.biz.dao.BizCalendarScheduleDao; +import com.jeesite.common.service.ServiceException; +import com.jeesite.common.config.Global; +import com.jeesite.common.validator.ValidatorUtils; +import com.jeesite.common.utils.excel.ExcelImport; +import org.springframework.web.multipart.MultipartFile; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; + +/** + * 日程信息Service + * @author gaoxq + * @version 2025-12-10 + */ +@Service +public class BizCalendarScheduleService extends CrudService { + + /** + * 获取单条数据 + * @param bizCalendarSchedule 主键 + */ + @Override + public BizCalendarSchedule get(BizCalendarSchedule bizCalendarSchedule) { + return super.get(bizCalendarSchedule); + } + + /** + * 查询分页数据 + * @param bizCalendarSchedule 查询条件 + * @param bizCalendarSchedule page 分页对象 + */ + @Override + public Page findPage(BizCalendarSchedule bizCalendarSchedule) { + return super.findPage(bizCalendarSchedule); + } + + /** + * 查询列表数据 + * @param bizCalendarSchedule 查询条件 + */ + @Override + public List findList(BizCalendarSchedule bizCalendarSchedule) { + return super.findList(bizCalendarSchedule); + } + + /** + * 保存数据(插入或更新) + * @param bizCalendarSchedule 数据对象 + */ + @Override + @Transactional + public void save(BizCalendarSchedule bizCalendarSchedule) { + super.save(bizCalendarSchedule); + } + + /** + * 导入数据 + * @param file 导入的数据文件 + */ + @Transactional + public String importData(MultipartFile file) { + if (file == null){ + throw new ServiceException(text("请选择导入的数据文件!")); + } + int successNum = 0; int failureNum = 0; + StringBuilder successMsg = new StringBuilder(); + StringBuilder failureMsg = new StringBuilder(); + try(ExcelImport ei = new ExcelImport(file, 2, 0)){ + List list = ei.getDataList(BizCalendarSchedule.class); + for (BizCalendarSchedule bizCalendarSchedule : list) { + try{ + ValidatorUtils.validateWithException(bizCalendarSchedule); + this.save(bizCalendarSchedule); + successNum++; + successMsg.append("
" + successNum + "、编号 " + bizCalendarSchedule.getId() + " 导入成功"); + } catch (Exception e) { + failureNum++; + String msg = "
" + failureNum + "、编号 " + bizCalendarSchedule.getId() + " 导入失败:"; + if (e instanceof ConstraintViolationException){ + ConstraintViolationException cve = (ConstraintViolationException)e; + for (ConstraintViolation violation : cve.getConstraintViolations()) { + msg += Global.getText(violation.getMessage()) + " ("+violation.getPropertyPath()+")"; + } + }else{ + msg += e.getMessage(); + } + failureMsg.append(msg); + logger.error(msg, e); + } + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + failureMsg.append(e.getMessage()); + return failureMsg.toString(); + } + if (failureNum > 0) { + failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); + throw new ServiceException(failureMsg.toString()); + }else{ + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:"); + } + return successMsg.toString(); + } + + /** + * 更新状态 + * @param bizCalendarSchedule 数据对象 + */ + @Override + @Transactional + public void updateStatus(BizCalendarSchedule bizCalendarSchedule) { + super.updateStatus(bizCalendarSchedule); + } + + /** + * 删除数据 + * @param bizCalendarSchedule 数据对象 + */ + @Override + @Transactional + public void delete(BizCalendarSchedule bizCalendarSchedule) { + super.delete(bizCalendarSchedule); + } + +} \ No newline at end of file diff --git a/web-api/src/main/java/com/jeesite/modules/biz/web/BizCalendarScheduleController.java b/web-api/src/main/java/com/jeesite/modules/biz/web/BizCalendarScheduleController.java new file mode 100644 index 00000000..6bd8afef --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/biz/web/BizCalendarScheduleController.java @@ -0,0 +1,156 @@ +package com.jeesite.modules.biz.web; + +import java.util.List; + +import com.jeesite.modules.app.utils.vDate; +import com.jeesite.modules.sys.entity.User; +import com.jeesite.modules.sys.utils.UserUtils; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.jeesite.common.config.Global; +import com.jeesite.common.collect.ListUtils; +import com.jeesite.common.entity.Page; +import com.jeesite.common.lang.DateUtils; +import com.jeesite.common.utils.excel.ExcelExport; +import com.jeesite.common.utils.excel.annotation.ExcelField.Type; +import org.springframework.web.multipart.MultipartFile; +import com.jeesite.common.web.BaseController; +import com.jeesite.modules.biz.entity.BizCalendarSchedule; +import com.jeesite.modules.biz.service.BizCalendarScheduleService; + +/** + * 日程信息Controller + * + * @author gaoxq + * @version 2025-12-10 + */ +@Controller +@RequestMapping(value = "${adminPath}/biz/calendarSchedule") +public class BizCalendarScheduleController extends BaseController { + + private final BizCalendarScheduleService bizCalendarScheduleService; + + public BizCalendarScheduleController(BizCalendarScheduleService bizCalendarScheduleService) { + this.bizCalendarScheduleService = bizCalendarScheduleService; + } + + /** + * 获取数据 + */ + @ModelAttribute + public BizCalendarSchedule get(String scheduleId, boolean isNewRecord) { + return bizCalendarScheduleService.get(scheduleId, isNewRecord); + } + + /** + * 查询列表 + */ + @RequiresPermissions("biz:calendarSchedule:view") + @RequestMapping(value = {"list", ""}) + public String list(BizCalendarSchedule bizCalendarSchedule, Model model) { + model.addAttribute("bizCalendarSchedule", bizCalendarSchedule); + return "modules/biz/bizCalendarScheduleList"; + } + + /** + * 查询列表数据 + */ + @RequiresPermissions("biz:calendarSchedule:view") + @RequestMapping(value = "listData") + @ResponseBody + public Page listData(BizCalendarSchedule bizCalendarSchedule, HttpServletRequest request, HttpServletResponse response) { + bizCalendarSchedule.setPage(new Page<>(request, response)); + Page page = bizCalendarScheduleService.findPage(bizCalendarSchedule); + return page; + } + + /** + * 查看编辑表单 + */ + @RequiresPermissions("biz:calendarSchedule:view") + @RequestMapping(value = "form") + public String form(BizCalendarSchedule bizCalendarSchedule, Model model) { + model.addAttribute("bizCalendarSchedule", bizCalendarSchedule); + return "modules/biz/bizCalendarScheduleForm"; + } + + /** + * 保存数据 + */ + @RequiresPermissions("biz:calendarSchedule:edit") + @PostMapping(value = "save") + @ResponseBody + public String save(@Validated BizCalendarSchedule bizCalendarSchedule) { + User user = UserUtils.getUser(); + User fUser = UserUtils.getByLoginCode(bizCalendarSchedule.getParticipantUser()); + bizCalendarSchedule.setCreatorUser(user.getLoginCode()); + bizCalendarSchedule.setParticipantName(fUser.getUserName()); + bizCalendarSchedule.setUpdateTime(vDate.getUpdateTime(bizCalendarSchedule.getIsNewRecord())); + bizCalendarScheduleService.save(bizCalendarSchedule); + return renderResult(Global.TRUE, text("保存日程信息成功!")); + } + + /** + * 导出数据 + */ + @RequiresPermissions("biz:calendarSchedule:view") + @RequestMapping(value = "exportData") + public void exportData(BizCalendarSchedule bizCalendarSchedule, HttpServletResponse response) { + List list = bizCalendarScheduleService.findList(bizCalendarSchedule); + String fileName = "日程信息" + DateUtils.getDate("yyyyMMddHHmmss") + ".xlsx"; + try (ExcelExport ee = new ExcelExport("日程信息", BizCalendarSchedule.class)) { + ee.setDataList(list).write(response, fileName); + } + } + + /** + * 下载模板 + */ + @RequiresPermissions("biz:calendarSchedule:view") + @RequestMapping(value = "importTemplate") + public void importTemplate(HttpServletResponse response) { + BizCalendarSchedule bizCalendarSchedule = new BizCalendarSchedule(); + List list = ListUtils.newArrayList(bizCalendarSchedule); + String fileName = "日程信息模板.xlsx"; + try (ExcelExport ee = new ExcelExport("日程信息", BizCalendarSchedule.class, Type.IMPORT)) { + ee.setDataList(list).write(response, fileName); + } + } + + /** + * 导入数据 + */ + @ResponseBody + @RequiresPermissions("biz:calendarSchedule:edit") + @PostMapping(value = "importData") + public String importData(MultipartFile file) { + try { + String message = bizCalendarScheduleService.importData(file); + return renderResult(Global.TRUE, "posfull:" + message); + } catch (Exception ex) { + return renderResult(Global.FALSE, "posfull:" + ex.getMessage()); + } + } + + /** + * 删除数据 + */ + @RequiresPermissions("biz:calendarSchedule:edit") + @RequestMapping(value = "delete") + @ResponseBody + public String delete(BizCalendarSchedule bizCalendarSchedule) { + bizCalendarScheduleService.delete(bizCalendarSchedule); + return renderResult(Global.TRUE, text("删除日程信息成功!")); + } + +} \ No newline at end of file diff --git a/web-api/src/main/resources/mappings/modules/biz/BizCalendarScheduleDao.xml b/web-api/src/main/resources/mappings/modules/biz/BizCalendarScheduleDao.xml new file mode 100644 index 00000000..9ba961c4 --- /dev/null +++ b/web-api/src/main/resources/mappings/modules/biz/BizCalendarScheduleDao.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/web-vue/packages/biz/api/biz/calendarSchedule.ts b/web-vue/packages/biz/api/biz/calendarSchedule.ts new file mode 100644 index 00000000..482b6129 --- /dev/null +++ b/web-vue/packages/biz/api/biz/calendarSchedule.ts @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + * @author gaoxq + */ +import { defHttp } from '@jeesite/core/utils/http/axios'; +import { useGlobSetting } from '@jeesite/core/hooks/setting'; +import { BasicModel, Page } from '@jeesite/core/api/model/baseModel'; +import { UploadApiResult } from '@jeesite/core/api/sys/upload'; +import { UploadFileParams } from '@jeesite/types/axios'; +import { AxiosProgressEvent } from 'axios'; + +const { ctxPath, adminPath } = useGlobSetting(); + +export interface BizCalendarSchedule extends BasicModel { + createTime?: string; // 记录时间 + scheduleId?: string; // 主键标识 + scheduleNo: string; // 日程编号 + title: string; // 日程标题 + content?: string; // 日程详情/备注 + startTime: string; // 日程开始时间 + endTime: string; // 日程结束时间 + allDay: string; // 是否全天 + location?: string; // 日程地点 + priority: string; // 优先等级 + ustatus: string; // 日程状态 + remindTime?: string; // 提醒时间 + creatorUser?: string; // 创建人账号 + creatorName?: string; // 创建人名称 + participantUser?: string; // 接收人账号 + participantName?: string; // 接收人名称 + updateTime?: string; // 更新时间 +} + +export const bizCalendarScheduleList = (params?: BizCalendarSchedule | any) => + defHttp.get({ url: adminPath + '/biz/calendarSchedule/list', params }); + +export const bizCalendarScheduleListData = (params?: BizCalendarSchedule | any) => + defHttp.post>({ url: adminPath + '/biz/calendarSchedule/listData', params }); + +export const bizCalendarScheduleForm = (params?: BizCalendarSchedule | any) => + defHttp.get({ url: adminPath + '/biz/calendarSchedule/form', params }); + +export const bizCalendarScheduleSave = (params?: any, data?: BizCalendarSchedule | any) => + defHttp.postJson({ url: adminPath + '/biz/calendarSchedule/save', params, data }); + +export const bizCalendarScheduleImportData = ( + params: UploadFileParams, + onUploadProgress: (progressEvent: AxiosProgressEvent) => void, +) => + defHttp.uploadFile( + { + url: ctxPath + adminPath + '/biz/calendarSchedule/importData', + onUploadProgress, + }, + params, + ); + +export const bizCalendarScheduleDelete = (params?: BizCalendarSchedule | any) => + defHttp.get({ url: adminPath + '/biz/calendarSchedule/delete', params }); diff --git a/web-vue/packages/biz/views/biz/calendarSchedule/form.vue b/web-vue/packages/biz/views/biz/calendarSchedule/form.vue new file mode 100644 index 00000000..d961b436 --- /dev/null +++ b/web-vue/packages/biz/views/biz/calendarSchedule/form.vue @@ -0,0 +1,188 @@ + + + diff --git a/web-vue/packages/biz/views/biz/calendarSchedule/formImport.vue b/web-vue/packages/biz/views/biz/calendarSchedule/formImport.vue new file mode 100644 index 00000000..53dcd8e7 --- /dev/null +++ b/web-vue/packages/biz/views/biz/calendarSchedule/formImport.vue @@ -0,0 +1,103 @@ + + + diff --git a/web-vue/packages/biz/views/biz/calendarSchedule/list.vue b/web-vue/packages/biz/views/biz/calendarSchedule/list.vue new file mode 100644 index 00000000..ab6cbde5 --- /dev/null +++ b/web-vue/packages/biz/views/biz/calendarSchedule/list.vue @@ -0,0 +1,311 @@ + + + diff --git a/web-vue/packages/biz/views/biz/dataReport/erp/components/ChartBarAccount.vue b/web-vue/packages/biz/views/biz/dataReport/erp/components/ChartBarAccount.vue index f34246ce..f7ec9377 100644 --- a/web-vue/packages/biz/views/biz/dataReport/erp/components/ChartBarAccount.vue +++ b/web-vue/packages/biz/views/biz/dataReport/erp/components/ChartBarAccount.vue @@ -201,7 +201,7 @@ const processTableData = () => { ); if (validData.length === 0) { - return { accountNames: [], series: [], bankDetailMap: {}, latestDate: '' }; + return { accountNames: [], series: [], bankDetailMap: {}, latestDate: '', sortedDates: [] }; } // 1. 获取所有日期并排序(支持季度/月份格式) @@ -287,7 +287,7 @@ const processTableData = () => { }; /** - * 初始化图表(X轴为银行名称,Tooltip展示月度明细) + * 初始化图表(X轴为银行名称,Tooltip改为表格形式展示) */ const initChart = () => { if (!chartDom.value) return; @@ -319,53 +319,77 @@ const initChart = () => { trigger: 'axis', axisPointer: { type: 'shadow' }, textStyle: { fontSize: 12 }, - padding: [10, 15], + padding: [12, 15], + // Tooltip重构为:标题 + 明细表格 + 汇总行 formatter: function(params: any) { if (!params || params.length === 0) return ''; // 获取当前银行名称 const bankName = params[0]?.axisValue || ''; const bankDetails = bankDetailMap[bankName] || {}; - // 生成各周期明细行 - let cycleRows = ''; + // 生成周期明细表格行 + let cycleTableRows = ''; + let hasData = false; sortedDates.forEach(date => { const detail = bankDetails[date] || { income: 0, expense: 0 }; const incomeYuan = convertToYuan(detail.income); const expenseYuan = convertToYuan(detail.expense); if (incomeYuan > 0 || expenseYuan > 0) { - cycleRows += ` -
- + hasData = true; + cycleTableRows += ` + + ${date} - - - 收入:${formatNumber(incomeYuan)} - 支出:${formatNumber(expenseYuan)} - -
+ + ${formatNumber(incomeYuan)} + ${formatNumber(expenseYuan)} + `; } }); + // 空明细处理 + if (!hasData) { + cycleTableRows = ` + + 暂无周期明细数据 + + `; + } + // 计算最新周期汇总 const latestDetail = bankDetails[latestDate] || { income: 0, expense: 0 }; const latestIncome = convertToYuan(latestDetail.income); const latestExpense = convertToYuan(latestDetail.expense); const netIncome = latestIncome - latestExpense; + // 完整表格化Tooltip结构 return ` -
${bankName}
- ${cycleRows} -
- 本期总收入: - - 收入:${formatNumber(latestIncome)} 元 - 支出:${formatNumber(latestExpense)} 元 - + +
${bankName}
+ + + + + + + + + + + ${cycleTableRows} + +
周期收入(元)支出(元)
+ +
+
+ 本期总收入:${formatNumber(latestIncome)} 元 + 本期总支出:${formatNumber(latestExpense)} 元 +
-
+
本期净收入:${formatNumber(netIncome)} 元
`; @@ -486,15 +510,16 @@ onUnmounted(() => { border-radius: 4px; /* 图例也添加圆角,保持风格统一 */ } -/* Tooltip样式 */ +/* Tooltip样式优化(适配表格) */ :deep(.echarts-tooltip) { border-radius: 8px; - padding: 10px; + padding: 12px !important; box-shadow: 0 2px 12px rgba(0,0,0,0.15); border: none; background: #fff; z-index: 9999 !important; - max-width: 400px; /* 限制Tooltip宽度,避免过宽 */ + min-width: 450px; /* 保证表格有足够宽度 */ + max-width: 500px; /* 限制最大宽度避免过宽 */ } /* 优化标签显示效果 */ @@ -511,4 +536,15 @@ onUnmounted(() => { word-break: keep-all; white-space: nowrap; } - + +/* Tooltip表格样式增强 */ +:deep(.echarts-tooltip table) { + width: 100%; + border-collapse: collapse; +} + +:deep(.echarts-tooltip th) { + font-weight: 600; + color: #666; +} + \ No newline at end of file diff --git a/web-vue/packages/biz/views/biz/dataReport/erp/components/ChartBarCycle.vue b/web-vue/packages/biz/views/biz/dataReport/erp/components/ChartBarCycle.vue index 93c62567..1c4a7cdc 100644 --- a/web-vue/packages/biz/views/biz/dataReport/erp/components/ChartBarCycle.vue +++ b/web-vue/packages/biz/views/biz/dataReport/erp/components/ChartBarCycle.vue @@ -216,8 +216,7 @@ const processTableData = () => { data: dateList.map(date => incomeTotalMap[date]), itemStyle: { ...baseBarConfig.itemStyle, - color: '#52c41a', // 收入绿色 - // 可选:收入柱子添加渐变效果,增强视觉体验 + // 收入柱子添加渐变效果,增强视觉体验 color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: '#73d13d' }, { offset: 1, color: '#52c41a' } @@ -235,8 +234,7 @@ const processTableData = () => { data: dateList.map(date => expenseTotalMap[date]), itemStyle: { ...baseBarConfig.itemStyle, - color: '#f5222d', // 支出红色 - // 可选:支出柱子添加渐变效果,增强视觉体验 + // 支出柱子添加渐变效果,增强视觉体验 color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ { offset: 0, color: '#ff4d4f' }, { offset: 1, color: '#f5222d' } @@ -259,7 +257,7 @@ const processTableData = () => { }; /** - * 初始化图表(改为总值显示,恢复原Tooltip格式) + * 初始化图表(改为总值显示,Tooltip改为表格形式) */ const initChart = () => { if (!chartDom.value) return; @@ -292,6 +290,7 @@ const initChart = () => { axisPointer: { type: 'shadow' }, textStyle: { fontSize: 12 }, padding: [10, 15], + // Tooltip改为表格形式展示 formatter: function(params: any) { if (!params || params.length === 0) return ''; const date = params[0]?.axisValue || ''; @@ -301,11 +300,11 @@ const initChart = () => { const expenseTotal = convertToYuan(expenseTotalMap[date] || 0); const netIncome = incomeTotal - expenseTotal; - let accountRows = ''; const accountDetails = accountDetailMap[date] || {}; const accountNames = Object.keys(accountDetails).sort(); - // 生成账户明细行(保持原格式) + // 生成账户明细表格行 + let accountTableRows = ''; accountNames.forEach(account => { const detail = accountDetails[account]; if (detail.income > 0 || detail.expense > 0) { @@ -313,32 +312,44 @@ const initChart = () => { const incomeValue = convertToYuan(detail.income); const expenseValue = convertToYuan(detail.expense); - accountRows += ` -
- + accountTableRows += ` + + ${account} - - - 收入:${formatNumber(incomeValue)} - 支出:${formatNumber(expenseValue)} - -
+ + ${formatNumber(incomeValue)} + ${formatNumber(expenseValue)} + `; } }); - // 保持原Tooltip的HTML结构 + // 完整的表格结构Tooltip return ` -
${date}
- ${accountRows} +
${date}
+ + + + + + + + + + + ${accountTableRows || ''} + +
账户名称收入(元)支出(元)
暂无明细数据
+
- + 总计 + 总收入:${formatNumber(incomeTotal)} 元 总支出:${formatNumber(expenseTotal)} 元
-
+
净收入:${formatNumber(netIncome)} 元
`; @@ -460,14 +471,15 @@ onUnmounted(() => { border-radius: 4px; /* 图例也添加圆角,保持风格统一 */ } -/* Tooltip样式 */ +/* Tooltip样式优化(适配表格) */ :deep(.echarts-tooltip) { border-radius: 8px; - padding: 10px; + padding: 12px !important; box-shadow: 0 2px 12px rgba(0,0,0,0.15); border: none; background: #fff; z-index: 9999 !important; + min-width: 400px; /* 保证表格有足够宽度 */ } /* 优化标签显示效果 */ @@ -484,4 +496,20 @@ onUnmounted(() => { word-break: keep-all; white-space: nowrap; } - + +/* Tooltip表格样式优化 */ +:deep(.echarts-tooltip table) { + width: 100%; + border-collapse: collapse; + margin: 4px 0; +} + +:deep(.echarts-tooltip th) { + font-weight: 600; + color: #666; +} + +:deep(.echarts-tooltip td, .echarts-tooltip th) { + border: 1px solid #eee; +} + \ No newline at end of file diff --git a/web-vue/packages/biz/views/biz/tableInfo/list.vue b/web-vue/packages/biz/views/biz/tableInfo/list.vue index f8544cd3..eea84243 100644 --- a/web-vue/packages/biz/views/biz/tableInfo/list.vue +++ b/web-vue/packages/biz/views/biz/tableInfo/list.vue @@ -179,7 +179,7 @@ dataIndex: 'updateTime', key: 'a.update_time', sorter: true, - width: 130, + width: 180, align: 'center', }, { diff --git a/web-vue/packages/core/layouts/views/desktop/workbench/components/MySchedule.vue b/web-vue/packages/core/layouts/views/desktop/workbench/components/MySchedule.vue index 3a74d9ea..6b982b16 100644 --- a/web-vue/packages/core/layouts/views/desktop/workbench/components/MySchedule.vue +++ b/web-vue/packages/core/layouts/views/desktop/workbench/components/MySchedule.vue @@ -214,7 +214,7 @@ /* 样式部分保持不变 */ .card-container { width: 100%; - height: 18vh; + height: 12vh; min-height: 160px; background-color: #e6f7ff; padding: 10px 0; diff --git a/web-vue/packages/core/layouts/views/desktop/workbench/components/calendar/form.vue b/web-vue/packages/core/layouts/views/desktop/workbench/components/calendar/form.vue new file mode 100644 index 00000000..477b9384 --- /dev/null +++ b/web-vue/packages/core/layouts/views/desktop/workbench/components/calendar/form.vue @@ -0,0 +1,189 @@ + + + diff --git a/web-vue/packages/core/layouts/views/desktop/workbench/components/calendar/formImport.vue b/web-vue/packages/core/layouts/views/desktop/workbench/components/calendar/formImport.vue new file mode 100644 index 00000000..53dcd8e7 --- /dev/null +++ b/web-vue/packages/core/layouts/views/desktop/workbench/components/calendar/formImport.vue @@ -0,0 +1,103 @@ + + + diff --git a/web-vue/packages/core/layouts/views/desktop/workbench/components/calendar/list.vue b/web-vue/packages/core/layouts/views/desktop/workbench/components/calendar/list.vue new file mode 100644 index 00000000..a0208eb3 --- /dev/null +++ b/web-vue/packages/core/layouts/views/desktop/workbench/components/calendar/list.vue @@ -0,0 +1,280 @@ + + + diff --git a/web-vue/packages/core/layouts/views/desktop/workbench/components/tableInfo/formImport.vue b/web-vue/packages/core/layouts/views/desktop/workbench/components/tableInfo/formImport.vue new file mode 100644 index 00000000..cd6c0615 --- /dev/null +++ b/web-vue/packages/core/layouts/views/desktop/workbench/components/tableInfo/formImport.vue @@ -0,0 +1,103 @@ + + + diff --git a/web-vue/packages/core/layouts/views/desktop/workbench/components/tableInfo/list.vue b/web-vue/packages/core/layouts/views/desktop/workbench/components/tableInfo/list.vue new file mode 100644 index 00000000..058d4975 --- /dev/null +++ b/web-vue/packages/core/layouts/views/desktop/workbench/components/tableInfo/list.vue @@ -0,0 +1,262 @@ + + + diff --git a/web-vue/packages/core/layouts/views/desktop/workbench/index.vue b/web-vue/packages/core/layouts/views/desktop/workbench/index.vue index e30e7710..d52179f2 100644 --- a/web-vue/packages/core/layouts/views/desktop/workbench/index.vue +++ b/web-vue/packages/core/layouts/views/desktop/workbench/index.vue @@ -1,16 +1,22 @@ + + \ No newline at end of file