效果展示
轻服务是什么
轻服务提供开箱即用的云服务和多终端可用的 Web IDE,让开发者无需关心服务器搭建、数据库部署、环境配置和线上运维等繁琐之事,只需专注于产品开发本身。 参考链接
对于我这种后端菜鸟来说,可以减轻非常大的负担(现在免费试用哦,快来白嫖)。
工作日历是什么
- 首先最基本的是日历。
- 然后就是能够插入当天的工作计划。
在本项目中所使用的技术栈
- Vue3(Web开发框架)
- Vue-router4(实现路由功能,简单点就是切换页面)
- Element Plus(懒癌福音,一套完整的组件库)
需要解决的几个问题
1.日历功能
首先我们解决显示日历的问题,这里借鉴了日历Demo的参考链接。
基本思路
- 首先获取当前时间,包括年、月、日。
- 得到日历中的第一天。
- 日历一共展示的天数。
- 使用循环,渲染出每一天。
// 1.获取当前时间
const curDate = new Date()
const year = curDate.getFullYear() // 年
const month = curDate.getMonth() // 月
const day = curDate.getDate() // 日
// 2. 获取日历中的第一天
// 这里举个例子,
// 假如12月1号是周三,那么日历中的第一天是11月28号。(参考上图)
// 计作开始时间startTime。
const getStartTime = (year, month) => {
// 获取当月第一天
let curMonthFirst = new Date(year, month, 1);
let weekDay = curMonthFirst.getDay();
return curMonthFirst - weekDay * 24 * 60 * 60 * 1000;
};
// 3.日历一共展示的天数
// (下一个月1号 - 这个月1号) / 一天的时间 = 这个月的天数
// 日历有时展示6周,有时展示5周
const getDayNum = (year, month) => {
// 获取当月第一天
let curMonthFirst = new Date(year, month, 1);
let nextMonthFirst = new Date(year, month + 1, 1);
let curTotalDays = (nextMonthFirst - curMonthFirst) / (24 * 60 * 60 * 1000);
// 当月第一天是周几
let weekDay = curMonthFirst.getDay();
if (36 - curTotalDays <= weekDay) {
return 42;
} else {
return 35;
}
};
// 4.使用循环,渲染出每一天
// 获取阳历可以使用new Date()
// 获取农历参考:
computed:{
monthDayNum() {
return getDayNum(this.year, this.month);
},
visibleCalendar() {
const calendatArr = [];
const startTime = getStartTime(this.year, this.month);
const monthDayNum = this.monthDayNum;
for (let i = 0; i < monthDayNum; i++) {
// 阳历
const date = new Date(startTime + i * 24 * 60 * 60 * 1000);
const year = date.getFullYear();
const month = date.getMonth();
const day = date.getDate(); //这个月第几号
// 农历
const lunar = calendar.solar2lunar(year, month + 1, day);
const IDayCn = lunar.IDayCn; //日
const IMonthCn = lunar.IMonthCn; //月
calendatArr.push({
date,
year,
month,
day,
IDayCn,
IMonthCn,
contents: [], // 当日计划
index: i,
});
}
return calendatArr;
},
}
<temple>
<ul class="calendar-view">
<li
v-for="(item, index) in visibleCalendar"
:key="index"
class="date-view"
:class="[
{ todayBg: isCurrentDay(item.day) }, //判断是否是当前
{ 'month-class': !isCurrentMonth(item.month) }, // 判断是否是当月
]"
@click="handleClickDay(item)"
>
//...
//这里可以渲染每一天的样式
</li>
</ul>
</temple>
显示农历的问题
2. 切换月份
通过修改数据中的year、month的值来实现
methods:{
// 上一个月
handlePrevMonth() {
this.contentsDays = {};
let prevMonth = new Date(this.year, this.month, 1);
prevMonth.setMonth(prevMonth.getMonth() - 1);
this.year = new Date(prevMonth).getFullYear();
this.month = new Date(prevMonth).getMonth();
},
// 下一个月
handleNextMonth() {
this.contentsDays = {};
let nextMonth = new Date(this.year, this.month, 1);
nextMonth.setMonth(nextMonth.getMonth() + 1);
this.year = new Date(nextMonth).getFullYear();
this.month = new Date(nextMonth).getMonth();
},
// 回到今天
handleToday() {
this.year = new Date().getFullYear();
this.month = new Date().getMonth();
},
}
3. 添加/删除工作内容
首先用v-model="addContent" 来双向绑定输入框的内容,如下图的展示效果。
添加内容: content是需要添加的内容,根据年月日调用 添加接口 删除内容: 获取删除的contentId,根据年月日调用 删除接口
methods:{
//添加内容
handleAddContent() {
const activateDay = this.visibleCalendar[this.activateIndex];
const { year, month, day } = activateDay;
const content = this.addContent;
this.addContent = "";
this.addLoading = true;
// 调用API
inspirecloud
.run("addRecord", { year, month, content, day: day - 1 })
.then((res) => {
if (res.success) {
this.getContentsByMonth();
this.addLoading = false;
ElMessage({
message: "添加成功",
type: "success",
});
} else {
this.addLoading = false;
ElMessage({
message: "添加失败",
type: "error",
});
}
});
},
// 删除内容
handleDelContent(index) {
const activateDay = this.visibleCalendar[this.activateIndex];
const { year, month } = activateDay;
const contentId = this.contentIdsDays[this.activateIndex][index];
this.addLoading = true;
// 调用API
inspirecloud
.run("deleteRecord", { year, month, contentId })
.then((res) => {
if (res) {
this.addLoading = false;
this.getContentsByMonth();
ElMessage({
message: "删除成功",
type: "success",
});
} else {
ElMessage({
message: "删除失败",
type: "error",
});
this.addLoading = true;
}
});
},
}
渲染出当天全部工作计划,这个结合小节1中的
<template>模块。index是visibleCalendar的下标。
<template>
<!-- 渲染某一天的全部计划 -->
<ul class="date-todoList">
<span
v-for="(content, index) in contentsDays[index]"
:key="index"
>{{ content }}</span
>
</ul>
</template>
4. 用户注册、登录问题
在轻服务中的云函数就是对应一个API,具体可以参考云函数nodejs版。
同时轻服务提供了完整的用户系统API,具体可以参考用户系统教程。
这里展示登录和注册的云函数
// loginByUsername.js
module.exports = async function (params, context) {
const { username, password } = params;
try {
const userInfo = await inspirecloud.user.login(
context, // 注意,调用所有 inspirecloud.user 相关接口时,都需要传入云函数中的 context
username,
password
);
return {
success: true,
userInfo,
};
} catch (e) {
return {
success: false,
message: e.message,
};
}
};
// createUser.js
module.exports = async function (params, context) {
// 从 params 中获取账号密码等参数
const { username, password } = params;
try {
const userInfo = await inspirecloud.user.register(
context, // 注意,调用所有 inspirecloud.user 相关接口时,都需要传入云函数中的 context
username,
password
);
return {
success: true,
userInfo,
};
} catch (e) {
return {
success: false,
message: e.message,
};
}
};
在前端项目中调用API
首先下载好SDK,
npm i @byteinspire/js-sdk
然后在页面中引用
import InspireCloud from "@byteinspire/js-sdk";
const serviceId = XXX; // 你的serviceId
const inspirecloud = new InspireCloud({ serviceId });
// 调用API
//inspirecloud.run('云函数的文件名',{参数}).then(res => {
// console.log(res)
//}
inspirecloud
.run("loginByUsername", { username, password })
.then((res) => {
if (res.success) {
this.formLabelAlign = {};
ElMessage({
message: "登录成功",
center: true,
type: "success",
});
this.$router.push("/home/calendar");
} else {
ElMessage({
message: res.message,
center: true,
type: "error",
});
this.isLogining = false;
}
})
.catch((error) => {
console.log(error);
});