diff --git a/scripts/build-all.sh b/scripts/build-all.sh index 0e6afce..877e305 100755 --- a/scripts/build-all.sh +++ b/scripts/build-all.sh @@ -74,8 +74,3 @@ echo -e "产物列表:" echo -e " - worklog-api.tar.gz (${API_SIZE})" echo -e " - wladmin/ (${WEB_SIZE})" echo -e " - wlmobile/ (${MOBILE_SIZE})" -echo "" -echo -e "部署命令示例:" -echo -e " scp ${DEPLOY_DIR}/worklog-api.tar.gz user@server:/opt/worklog/" -echo -e " scp -r ${DEPLOY_DIR}/wladmin user@server:/var/www/worklog/" -echo -e " scp -r ${DEPLOY_DIR}/wlmobile user@server:/var/www/worklog/" diff --git a/scripts/build-mobile.sh b/scripts/build-mobile.sh index 1e667bd..c092970 100755 --- a/scripts/build-mobile.sh +++ b/scripts/build-mobile.sh @@ -52,12 +52,15 @@ fi DIST_SIZE=$(du -sh dist | cut -f1) DIST_FILES=$(find dist -type f | wc -l) +# 部署到 deploy 目录 +echo -e "${YELLOW}部署到 ${DEPLOY_DIR}/wlmobile/...${NC}" +mkdir -p ${DEPLOY_DIR}/wlmobile +rm -rf ${DEPLOY_DIR}/wlmobile/* +cp -r dist/* ${DEPLOY_DIR}/wlmobile/ + echo -e "${GREEN}=========================================${NC}" -echo -e "${GREEN}构建完成!${NC}" +echo -e "${GREEN}构建并部署完成!${NC}" echo -e "${GREEN}=========================================${NC}" -echo -e "输出目录: ${MOBILE_DIR}/dist" +echo -e "输出目录: ${DEPLOY_DIR}/wlmobile/" echo -e "总大小: ${DIST_SIZE}" echo -e "文件数量: ${DIST_FILES}" -echo "" -echo -e "部署目录: ${DEPLOY_DIR}/wlmobile/" -echo -e "部署命令: cp -r dist/* ${DEPLOY_DIR}/wlmobile/" diff --git a/scripts/build-web.sh b/scripts/build-web.sh index 6ebe925..8539871 100755 --- a/scripts/build-web.sh +++ b/scripts/build-web.sh @@ -52,12 +52,15 @@ fi DIST_SIZE=$(du -sh dist | cut -f1) DIST_FILES=$(find dist -type f | wc -l) +# 部署到 deploy 目录 +echo -e "${YELLOW}部署到 ${DEPLOY_DIR}/wladmin/...${NC}" +mkdir -p ${DEPLOY_DIR}/wladmin +rm -rf ${DEPLOY_DIR}/wladmin/* +cp -r dist/* ${DEPLOY_DIR}/wladmin/ + echo -e "${GREEN}=========================================${NC}" -echo -e "${GREEN}构建完成!${NC}" +echo -e "${GREEN}构建并部署完成!${NC}" echo -e "${GREEN}=========================================${NC}" -echo -e "输出目录: ${WEB_DIR}/dist" +echo -e "输出目录: ${DEPLOY_DIR}/wladmin/" echo -e "总大小: ${DIST_SIZE}" echo -e "文件数量: ${DIST_FILES}" -echo "" -echo -e "部署目录: ${DEPLOY_DIR}/wladmin/" -echo -e "部署命令: cp -r dist/* ${DEPLOY_DIR}/wladmin/" diff --git a/sql/init_database.sql b/sql/init_database.sql index 0b3a653..e3e6893 100644 --- a/sql/init_database.sql +++ b/sql/init_database.sql @@ -94,6 +94,7 @@ CREATE TABLE `work_log` ( `id` VARCHAR(20) NOT NULL COMMENT '日志ID(雪花算法生成)', `user_id` VARCHAR(20) NOT NULL COMMENT '记录人ID', `log_date` DATE NOT NULL COMMENT '日志日期', + `title` VARCHAR(200) DEFAULT NULL COMMENT '日志标题', `record_time` DATETIME NOT NULL COMMENT '记录时间', `content` TEXT NOT NULL COMMENT '日志内容(Markdown格式,最大2000汉字)', `template_id` VARCHAR(20) DEFAULT NULL COMMENT '使用模板ID', diff --git a/worklog-api/src/main/java/com/wjbl/worklog/controller/LogController.java b/worklog-api/src/main/java/com/wjbl/worklog/controller/LogController.java index 34c78d6..bedfa94 100644 --- a/worklog-api/src/main/java/com/wjbl/worklog/controller/LogController.java +++ b/worklog-api/src/main/java/com/wjbl/worklog/controller/LogController.java @@ -16,6 +16,8 @@ import org.springframework.format.annotation.DateTimeFormat; import org.springframework.web.bind.annotation.*; import java.time.LocalDate; +import java.util.List; +import java.util.Set; /** * 日志控制器 @@ -117,4 +119,30 @@ public class LogController { logService.deleteLog(id); return Result.success(); } + + /** + * 获取日历数据(有日志的日期列表) + */ + @Operation(summary = "获取日历数据", description = "获取指定月份有日志的日期列表") + @GetMapping("/calendar") + public Result> getCalendarData( + @Parameter(description = "年份") @RequestParam Integer year, + @Parameter(description = "月份(1-12)") @RequestParam Integer month) { + Set dates = logService.getLogDatesByMonth(year, month); + List dateStrings = dates.stream() + .map(LocalDate::toString) + .toList(); + return Result.success(dateStrings); + } + + /** + * 根据日期获取日志 + */ + @Operation(summary = "根据日期获取日志", description = "获取当前用户指定日期的日志") + @GetMapping("/by-date") + public Result getLogByDate( + @Parameter(description = "日期(yyyy-MM-dd)") @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate date) { + LogVO log = logService.getLogByDate(date); + return Result.success(log); + } } diff --git a/worklog-api/src/main/java/com/wjbl/worklog/data/entity/WorkLog.java b/worklog-api/src/main/java/com/wjbl/worklog/data/entity/WorkLog.java index d2dd213..1fb4ce8 100644 --- a/worklog-api/src/main/java/com/wjbl/worklog/data/entity/WorkLog.java +++ b/worklog-api/src/main/java/com/wjbl/worklog/data/entity/WorkLog.java @@ -33,6 +33,11 @@ public class WorkLog implements Serializable { */ private LocalDate logDate; + /** + * 日志标题 + */ + private String title; + /** * 记录时间 */ diff --git a/worklog-api/src/main/java/com/wjbl/worklog/data/service/WorkLogDataService.java b/worklog-api/src/main/java/com/wjbl/worklog/data/service/WorkLogDataService.java index 8544fd1..aa83ab9 100644 --- a/worklog-api/src/main/java/com/wjbl/worklog/data/service/WorkLogDataService.java +++ b/worklog-api/src/main/java/com/wjbl/worklog/data/service/WorkLogDataService.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService; import com.wjbl.worklog.data.entity.WorkLog; import java.time.LocalDate; +import java.util.Set; /** * 工作日志数据服务接口 @@ -42,4 +43,14 @@ public interface WorkLogDataService extends IService { * @return 工作日志 */ WorkLog getByUserIdAndLogDate(String userId, LocalDate logDate); + + /** + * 获取指定用户指定月份有日志的日期列表 + * + * @param userId 用户ID + * @param year 年份 + * @param month 月份(1-12) + * @return 有日志的日期集合 + */ + Set getLogDatesByMonth(String userId, int year, int month); } diff --git a/worklog-api/src/main/java/com/wjbl/worklog/data/service/impl/WorkLogDataServiceImpl.java b/worklog-api/src/main/java/com/wjbl/worklog/data/service/impl/WorkLogDataServiceImpl.java index 2f86ee3..5bdb27d 100644 --- a/worklog-api/src/main/java/com/wjbl/worklog/data/service/impl/WorkLogDataServiceImpl.java +++ b/worklog-api/src/main/java/com/wjbl/worklog/data/service/impl/WorkLogDataServiceImpl.java @@ -9,6 +9,8 @@ import com.wjbl.worklog.data.service.WorkLogDataService; import org.springframework.stereotype.Service; import java.time.LocalDate; +import java.util.HashSet; +import java.util.Set; /** * 工作日志数据服务实现类 @@ -46,4 +48,21 @@ public class WorkLogDataServiceImpl extends ServiceImpl .eq(WorkLog::getLogDate, logDate) .one(); } + + @Override + public Set getLogDatesByMonth(String userId, int year, int month) { + LocalDate startDate = LocalDate.of(year, month, 1); + LocalDate endDate = startDate.plusMonths(1).minusDays(1); + + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(WorkLog::getUserId, userId) + .ge(WorkLog::getLogDate, startDate) + .le(WorkLog::getLogDate, endDate) + .select(WorkLog::getLogDate); + + Set dates = new HashSet<>(); + list(wrapper).forEach(log -> dates.add(log.getLogDate())); + + return dates; + } } diff --git a/worklog-api/src/main/java/com/wjbl/worklog/dto/LogCreateDTO.java b/worklog-api/src/main/java/com/wjbl/worklog/dto/LogCreateDTO.java index c34202a..9961d65 100644 --- a/worklog-api/src/main/java/com/wjbl/worklog/dto/LogCreateDTO.java +++ b/worklog-api/src/main/java/com/wjbl/worklog/dto/LogCreateDTO.java @@ -22,6 +22,13 @@ public class LogCreateDTO implements Serializable { @Schema(description = "日志日期,默认当天") private LocalDate logDate; + /** + * 日志标题 + */ + @NotBlank(message = "标题不能为空") + @Schema(description = "日志标题", requiredMode = Schema.RequiredMode.REQUIRED) + private String title; + /** * 日志内容(Markdown格式) */ diff --git a/worklog-api/src/main/java/com/wjbl/worklog/dto/LogUpdateDTO.java b/worklog-api/src/main/java/com/wjbl/worklog/dto/LogUpdateDTO.java index ee3b9f5..67445d4 100644 --- a/worklog-api/src/main/java/com/wjbl/worklog/dto/LogUpdateDTO.java +++ b/worklog-api/src/main/java/com/wjbl/worklog/dto/LogUpdateDTO.java @@ -14,6 +14,12 @@ public class LogUpdateDTO implements Serializable { private static final long serialVersionUID = 1L; + /** + * 日志标题 + */ + @Schema(description = "日志标题") + private String title; + /** * 日志内容(Markdown格式) */ diff --git a/worklog-api/src/main/java/com/wjbl/worklog/service/LogService.java b/worklog-api/src/main/java/com/wjbl/worklog/service/LogService.java index b9216ee..5f298cb 100644 --- a/worklog-api/src/main/java/com/wjbl/worklog/service/LogService.java +++ b/worklog-api/src/main/java/com/wjbl/worklog/service/LogService.java @@ -6,6 +6,7 @@ import com.wjbl.worklog.dto.LogUpdateDTO; import com.wjbl.worklog.vo.LogVO; import java.time.LocalDate; +import java.util.Set; /** * 日志服务接口 @@ -66,4 +67,21 @@ public interface LogService { * @return 日志信息 */ LogVO getLogById(String id); + + /** + * 获取指定月份有日志的日期列表 + * + * @param year 年份 + * @param month 月份(1-12) + * @return 有日志的日期集合 + */ + Set getLogDatesByMonth(int year, int month); + + /** + * 根据日期获取日志 + * + * @param date 日期 + * @return 日志信息(如果不存在返回null) + */ + LogVO getLogByDate(LocalDate date); } diff --git a/worklog-api/src/main/java/com/wjbl/worklog/service/impl/LogServiceImpl.java b/worklog-api/src/main/java/com/wjbl/worklog/service/impl/LogServiceImpl.java index b0fa9a9..6738904 100644 --- a/worklog-api/src/main/java/com/wjbl/worklog/service/impl/LogServiceImpl.java +++ b/worklog-api/src/main/java/com/wjbl/worklog/service/impl/LogServiceImpl.java @@ -1,9 +1,12 @@ package com.wjbl.worklog.service.impl; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.wjbl.worklog.common.context.UserContext; import com.wjbl.worklog.common.exception.BusinessException; +import com.wjbl.worklog.data.entity.User; import com.wjbl.worklog.data.entity.WorkLog; +import com.wjbl.worklog.data.service.UserDataService; import com.wjbl.worklog.data.service.WorkLogDataService; import com.wjbl.worklog.dto.LogCreateDTO; import com.wjbl.worklog.dto.LogUpdateDTO; @@ -16,6 +19,7 @@ import org.springframework.stereotype.Service; import java.time.LocalDate; import java.time.LocalDateTime; +import java.util.Set; /** * 日志服务实现类 @@ -26,6 +30,7 @@ import java.time.LocalDateTime; public class LogServiceImpl implements LogService { private final WorkLogDataService workLogDataService; + private final UserDataService userDataService; @Override public LogVO createLog(LogCreateDTO dto) { @@ -42,6 +47,7 @@ public class LogServiceImpl implements LogService { WorkLog workLog = new WorkLog(); workLog.setUserId(currentUserId); workLog.setLogDate(logDate); + workLog.setTitle(dto.getTitle()); workLog.setRecordTime(LocalDateTime.now()); workLog.setContent(dto.getContent()); workLog.setTemplateId(dto.getTemplateId()); @@ -77,6 +83,9 @@ public class LogServiceImpl implements LogService { } // 更新日志 + if (dto.getTitle() != null) { + workLog.setTitle(dto.getTitle()); + } if (dto.getContent() != null) { workLog.setContent(dto.getContent()); } @@ -107,7 +116,13 @@ public class LogServiceImpl implements LogService { throw new BusinessException("无权删除他人的日志"); } - workLogDataService.removeById(id); + // 使用 UpdateWrapper 执行逻辑删除,同时设置 updated_by + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>(); + updateWrapper.eq(WorkLog::getId, id) + .set(WorkLog::getUpdatedBy, currentUserId) + .set(WorkLog::getUpdatedTime, LocalDateTime.now()) + .set(WorkLog::getDeleted, 1); + workLogDataService.update(updateWrapper); log.info("删除工作日志成功:ID={}", id); } @@ -167,6 +182,31 @@ public class LogServiceImpl implements LogService { private LogVO convertToVO(WorkLog workLog) { LogVO vo = new LogVO(); BeanUtils.copyProperties(workLog, vo); + + // 填充用户姓名 + if (workLog.getUserId() != null) { + User user = userDataService.getById(workLog.getUserId()); + if (user != null) { + vo.setUserName(user.getName()); + } + } + return vo; } + + @Override + public Set getLogDatesByMonth(int year, int month) { + String currentUserId = UserContext.getUserId(); + return workLogDataService.getLogDatesByMonth(currentUserId, year, month); + } + + @Override + public LogVO getLogByDate(LocalDate date) { + String currentUserId = UserContext.getUserId(); + WorkLog workLog = workLogDataService.getByUserIdAndLogDate(currentUserId, date); + if (workLog == null) { + return null; + } + return convertToVO(workLog); + } } diff --git a/worklog-api/src/main/java/com/wjbl/worklog/vo/LogVO.java b/worklog-api/src/main/java/com/wjbl/worklog/vo/LogVO.java index d36f46e..5379d9c 100644 --- a/worklog-api/src/main/java/com/wjbl/worklog/vo/LogVO.java +++ b/worklog-api/src/main/java/com/wjbl/worklog/vo/LogVO.java @@ -28,12 +28,24 @@ public class LogVO implements Serializable { @Schema(description = "用户ID") private String userId; + /** + * 用户姓名 + */ + @Schema(description = "用户姓名") + private String userName; + /** * 日志日期 */ @Schema(description = "日志日期") private LocalDate logDate; + /** + * 日志标题 + */ + @Schema(description = "日志标题") + private String title; + /** * 日志内容(Markdown格式) */ diff --git a/worklog-api/src/test/java/com/wjbl/worklog/service/LogServiceTest.java b/worklog-api/src/test/java/com/wjbl/worklog/service/LogServiceTest.java index a6b9def..a444b60 100644 --- a/worklog-api/src/test/java/com/wjbl/worklog/service/LogServiceTest.java +++ b/worklog-api/src/test/java/com/wjbl/worklog/service/LogServiceTest.java @@ -43,6 +43,7 @@ class LogServiceTest { testLog.setId("log-id-123"); testLog.setUserId("user-id-123"); testLog.setLogDate(LocalDate.now()); + testLog.setTitle("测试日志标题"); testLog.setContent("今天完成了xxx任务"); testLog.setDeleted(0); @@ -56,6 +57,7 @@ class LogServiceTest { void createLog_success() { // Given LogCreateDTO dto = new LogCreateDTO(); + dto.setTitle("新日志标题"); dto.setContent("日志内容"); dto.setLogDate(LocalDate.now()); @@ -67,6 +69,7 @@ class LogServiceTest { // Then assertNotNull(result); + assertEquals("新日志标题", result.getTitle()); assertEquals("日志内容", result.getContent()); verify(workLogDataService).save(any(WorkLog.class)); } @@ -76,6 +79,7 @@ class LogServiceTest { void createLog_alreadyExists() { // Given LogCreateDTO dto = new LogCreateDTO(); + dto.setTitle("新日志标题"); dto.setContent("日志内容"); dto.setLogDate(LocalDate.now()); @@ -91,6 +95,7 @@ class LogServiceTest { void updateLog_success_ownLog() { // Given LogUpdateDTO dto = new LogUpdateDTO(); + dto.setTitle("更新后的标题"); dto.setContent("更新后的内容"); when(workLogDataService.getById("log-id-123")).thenReturn(testLog); @@ -101,6 +106,7 @@ class LogServiceTest { // Then assertNotNull(result); + assertEquals("更新后的标题", result.getTitle()); assertEquals("更新后的内容", result.getContent()); } @@ -114,6 +120,7 @@ class LogServiceTest { otherUserLog.setLogDate(LocalDate.now()); LogUpdateDTO dto = new LogUpdateDTO(); + dto.setTitle("更新后的标题"); dto.setContent("更新后的内容"); when(workLogDataService.getById("other-log-id")).thenReturn(otherUserLog); @@ -136,6 +143,7 @@ class LogServiceTest { otherUserLog.setLogDate(LocalDate.now()); LogUpdateDTO dto = new LogUpdateDTO(); + dto.setTitle("管理员更新标题"); dto.setContent("管理员更新内容"); when(workLogDataService.getById("other-log-id")).thenReturn(otherUserLog); @@ -146,6 +154,7 @@ class LogServiceTest { // Then assertNotNull(result); + assertEquals("管理员更新标题", result.getTitle()); assertEquals("管理员更新内容", result.getContent()); } @@ -189,6 +198,7 @@ class LogServiceTest { // Then assertNotNull(result); + assertEquals("测试日志标题", result.getTitle()); assertEquals("今天完成了xxx任务", result.getContent()); } diff --git a/worklog-mobile/public/logo.svg b/worklog-mobile/public/logo.svg new file mode 100644 index 0000000..87f6e7a --- /dev/null +++ b/worklog-mobile/public/logo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/worklog-mobile/src/api/log.ts b/worklog-mobile/src/api/log.ts index d44a4e8..d0e1f74 100644 --- a/worklog-mobile/src/api/log.ts +++ b/worklog-mobile/src/api/log.ts @@ -5,6 +5,7 @@ import { request } from '@/utils/request' export interface Log { id: string userId: string + userName: string logDate: string title: string content: string @@ -67,3 +68,13 @@ export function updateLog(id: string, data: UpdateLogParams): Promise { export function deleteLog(id: string): Promise { return request.delete(`/log/${id}`) } + +// 获取日历数据(有日志的日期列表) +export function getCalendarData(year: number, month: number): Promise { + return request.get('/log/calendar', { params: { year, month } }) +} + +// 获取指定日期的日志 +export function getLogByDate(date: string): Promise { + return request.get('/log/by-date', { params: { date } }) +} diff --git a/worklog-mobile/src/api/template.ts b/worklog-mobile/src/api/template.ts index 19bed31..e50e49e 100644 --- a/worklog-mobile/src/api/template.ts +++ b/worklog-mobile/src/api/template.ts @@ -6,11 +6,12 @@ export interface Template { id: string templateName: string content: string + instruction?: string status: number createdTime: string } // 获取启用的模板列表 export function listEnabledTemplates(): Promise { - return request.get('/template/enabled') + return request.get('/template/list') } diff --git a/worklog-mobile/src/router/index.ts b/worklog-mobile/src/router/index.ts index a3a87c8..e3ab1cb 100644 --- a/worklog-mobile/src/router/index.ts +++ b/worklog-mobile/src/router/index.ts @@ -15,6 +15,12 @@ const routes: RouteRecordRaw[] = [ component: () => import('@/views/home/index.vue'), meta: { requiresAuth: true } }, + { + path: '/mine', + name: 'Mine', + component: () => import('@/views/mine/index.vue'), + meta: { requiresAuth: true } + }, { path: '/log', name: 'LogList', @@ -42,7 +48,7 @@ const routes: RouteRecordRaw[] = [ ] const router = createRouter({ - history: createWebHistory(), + history: createWebHistory('/wlmobile/'), routes }) diff --git a/worklog-mobile/src/views/home/index.vue b/worklog-mobile/src/views/home/index.vue index f14388a..9c13416 100644 --- a/worklog-mobile/src/views/home/index.vue +++ b/worklog-mobile/src/views/home/index.vue @@ -3,78 +3,461 @@
- - - - - + + + +
+ + {{ currentYear }}年{{ currentMonth }}月 + +
+ + +
+ 已记录 + 未记录 +
- - - - - - - + + + + + - - -
- 退出登录 -
+ + +
+ + + + + + + +
+
+ + + + + + 首页 - 日志 + 我的 + + diff --git a/worklog-mobile/src/views/log/create.vue b/worklog-mobile/src/views/log/create.vue index dee2966..e9d2a01 100644 --- a/worklog-mobile/src/views/log/create.vue +++ b/worklog-mobile/src/views/log/create.vue @@ -74,13 +74,14 @@ diff --git a/worklog-mobile/src/views/login/index.vue b/worklog-mobile/src/views/login/index.vue index 04c3dc9..0486198 100644 --- a/worklog-mobile/src/views/login/index.vue +++ b/worklog-mobile/src/views/login/index.vue @@ -1,34 +1,50 @@ @@ -63,14 +79,135 @@ async function handleLogin() { diff --git a/worklog-mobile/src/views/mine/index.vue b/worklog-mobile/src/views/mine/index.vue new file mode 100644 index 0000000..466f970 --- /dev/null +++ b/worklog-mobile/src/views/mine/index.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/worklog-web/src/router/index.ts b/worklog-web/src/router/index.ts index 6beac70..321bce5 100644 --- a/worklog-web/src/router/index.ts +++ b/worklog-web/src/router/index.ts @@ -38,7 +38,7 @@ const routes: RouteRecordRaw[] = [ ] const router = createRouter({ - history: createWebHistory(), + history: createWebHistory('/wladmin/'), routes })