项目名称:任务协作小程序
项目目标:开发一个基于微信小程序平台的任务协作应用,帮助团队成员更好地管理和跟踪任务,提高协作效率和质量。
功能需求:
- 用户管理
- 支持微信一键登录,利用微信提供的登录能力,简化用户注册流程。
- 用户与所属机构关联,同机构用户数据一致。
- 个人中心允许用户查看和管理个人信息,提供头像、昵称等的修改功能。
- 任务看板
- 任务看板以列表和卡片的形式展示任务,采用看板式设计,任务状态一目了然。可以拖拽移动任务卡片,便于直观地管理任务。
- 每个任务卡片设计醒目,包括标题、负责人、截止日期等关键信息。
- 任务卡片可以设置优先级,用不同颜色或图标表示。
- 任务看板分为待办、进行中、已完成等多个列表,表示任务的不同状态。
- 点击任务卡片可以查看和编辑任务详情,包括描述、子任务、附件、评论等。注意界面平滑切换,保证信息的一致性和流畅性。
- 任务可以多层级分解为子任务,子任务完成后自动更新父任务进度,可以用进度条等形式直观展示。
- 任务支持协作讨论和评论,可以@相关人员。
- 所有任务操作自动记录到值班日志,注意控制权限,如任务的查看和编辑权限。
- 值班日志
- 值班日志由任务操作、故障记录、手动输入三部分组成,自动归类整理汇总。
- 字段包括但不限于日期、班次、人员、工作内容等,可以考虑允许一定程度的自定义。
- 支持手动填写其他工作内容。
- 可导出为格式化的 TXT 文件,文件名称格式为"值班日志_日期_班次.txt"。导出时需要鉴权,控制值班日志的查看和导出权限。
- 故障记录
- 记录故障发生时间、描述、影响范围、原因等关键信息。
- 关联到相应任务,形成闭环的故障处理流程。
- 自动生成预防性维护任务,提高系统可靠性。
- 关键信息自动记入值班日志,与任务、日志形成联动。
- 提供故障统计分析功能,为运维优化提供数据支持。可利用小程序云开发的云函数和云数据库能力。
- 文档共享
- 以列表形式展示共享文档。
- 点击文档,跳转到腾讯文档等在线文档页面。
- 注意文档的鉴权,只有相关人员可查看、编辑文档。
- 通知提醒
- 新任务分配时,自动推送小程序通知,提醒相关用户。
- 可以考虑提供多种提醒方式,如微信订阅消息、邮件、短信等。
交互设计建议:
任务看板布局清晰,可拖拽操作,便于直观管理任务。
2. 任务卡片设计醒目,关键信息一目了然,支持快速编辑。
3. 任务列表和任务详情界面平滑切换,保证信息的一致性和流畅性。
4. 界面整体布局简洁明了,突出重点信息。合理使用 tab、列表、卡片等组件。
5. 表单填写、任务操作等提供引导和及时反馈,如填写提示、完成提示、进度展示等。
6. 注意权限控制,如任务的查看和编辑权限、值班日志的查看和导出权限等。
技术建议:
- 采用微信小程序云开发方案,利用其提供的云函数、云存储、云数据库等能力,加速开发进程。
- 数据存储可以考虑 JSON 格式,便于前端解析展示。存储和获取都需要进行用户鉴权。
- 导出功能可由前端生成 TXT 文件,然后以二进制形式下载。后端提供数据接口支持。
- 评论、通知、导出等及时性要求高的功能,可以考虑合理利用缓存优化性能。
- 故障记录、统计分析等计算量大的功能,可以利用小程序云开发的云函数和云数据库能力。
- 任务看板的拖拽操作需要合理控制,避免误操作。可以考虑在拖拽时添加视觉反馈,如阴影、高亮等。
- 任务看板的性能优化很重要,尤其是任务数量较多时。可以考虑分页加载、懒加载等技术。
- 离线支持可以考虑利用小程序的本地存储,定期与服务器同步数据,保证离线时也能使用基本功能。
安全与权限:
- 重视数据安全,涉及隐私的数据要加密存储,传输过程也要加密。
- 严格控制数据访问权限,如任务的查看和编辑权限、值班日志的查看和导出权限等。
- 用户登录时进行身份验证,保证只有合法用户才能访问数据。
- 定期备份数据,制定数据恢复预案,最大限度减少数据丢失风险。
- 编写安全代码,防范常见的 Web 攻击,如 XSS、CSRF、SQL 注入等。
其他建议:
- 提供完善的帮助文档和用户指南,方便用户学习和使用。
- 建立用户反馈渠道,收集用户意见,不断优化产品。
- 制定合理的开发计划和迭代策略,逐步完善功能,提高用户满意度。
- 注重代码质量,编写清晰、易维护的代码,必要时编写单元测试,提高代码可靠性。
- 密切关注小程序平台的更新和变化,及时调整开发策略,充分利用新功能。
任务协作小程序设计了如下目录结构:
│ app.js
│ app.json
│ app.wxss
│
├─pages
│ ├─index
│ │ index.js
│ │ index.json
│ │ index.wxml
│ │ index.wxss
│ │
│ ├─login
│ │ login.js
│ │ login.json
│ │ login.wxml
│ │ login.wxss
│ │
│ ├─personal
│ │ personal.js
│ │ personal.json
│ │ personal.wxml
│ │ personal.wxss
│ │
│ ├─taskboard
│ │ taskboard.js
│ │ taskboard.json
│ │ taskboard.wxml
│ │ taskboard.wxss
│ │
│ ├─taskdetail
│ │ taskdetail.js
│ │ taskdetail.json
│ │ taskdetail.wxml
│ │ taskdetail.wxss
│ │
│ ├─dutylog
│ │ dutylog.js
│ │ dutylog.json
│ │ dutylog.wxml
│ │ dutylog.wxss
│ │
│ ├─faultrecord
│ │ faultrecord.js
│ │ faultrecord.json
│ │ faultrecord.wxml
│ │ faultrecord.wxss
│ │
│ └─doclist
│ doclist.js
│ doclist.json
│ doclist.wxml
│ doclist.wxss
│
├─components
│ ├─taskcard
│ │ taskcard.js
│ │ taskcard.json
│ │ taskcard.wxml
│ │ taskcard.wxss
│ │
│ └─faultitem
│ faultitem.js
│ faultitem.json
│ faultitem.wxml
│ faultitem.wxss
│
├─utils
│ util.js
│ auth.js
│ request.js
│
├─services
│ user.js
│ task.js
│ dutylog.js
│ fault.js
│ doc.js
│
└─cloud-functions
├─login
│ index.js
│ package.json
│
├─taskops
│ index.js
│ package.json
│
├─faultops
│ index.js
│ package.json
│
└─docops
index.js
package.json
app.js
// app.js
App({
onLaunch:
function
()
{
// 初始化云开发环境
wx
.cloud
.init({
env:
'your-env-id',
traceUser:
true,
})
},
globalData:
{
userInfo:
null
}
})
app.json
{
"pages": [
"pages/index/index",
"pages/login/login",
"pages/personal/personal",
"pages/taskboard/taskboard",
"pages/taskdetail/taskdetail",
"pages/dutylog/dutylog",
"pages/faultrecord/faultrecord",
"pages/doclist/doclist"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "
任务协作
",
"navigationBarTextStyle": "black"
},
"sitemapLocation": "sitemap.json",
"style": "v2"
}
pages/login/login.wxml
<!--login.wxml-->
<button open-type="getUserInfo" bindgetuserinfo="onGetUserInfo">微信登录
</button>
pages/login/login.js
// login.js
Page({
onGetUserInfo:
function(e)
{
if
(!e
.detail
.userInfo
)
{
// 用户拒绝授权
return;
}
// 执行登录,获取用户信息
wx
.cloud
.callFunction({
name:
'login',
data:
{},
success:
res
=>
{
console
.log('[云函数] [login] user openid: ', res
.result
.openid
)
app
.globalData
.userInfo
= e
.detail
.userInfo
app
.globalData
.openid
= res
.result
.openid
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
if
(this.userInfoReadyCallback
)
{
this.userInfoReadyCallback(res
)
}
},
fail:
err
=>
{
console
.error('[云函数] [login] 调用失败', err
)
}
})
},
})
pages/taskboard/taskboard.wxml
<!--taskboard.wxml-->
<view class="container">
<view class="task-column">
<view class="task-column-title">待办
</view>
<view wx:for="{{todoTasks}}" wx:key="id">
<taskcard task="{{item}}"></taskcard>
</view>
</view>
<view class="task-column">
<view class="task-column-title">进行中
</view>
<view wx:for="{{doingTasks}}" wx:key="id">
<taskcard task="{{item}}"></taskcard>
</view>
</view>
<view class="task-column">
<view class="task-column-title">已完成
</view>
<view wx:for="{{doneTasks}}" wx:key="id">
<taskcard task="{{item}}"></taskcard>
</view>
</view>
</view>
pages/taskboard/taskboard.js
// taskboard.js
const app
=
getApp()
Page({
data:
{
todoTasks:
[],
doingTasks:
[],
doneTasks:
[],
},
onLoad:
function()
{
this.getTasks()
},
getTasks:
function()
{ // 从云数据库获取任务数据
wx.cloud.callFunction({
name: 'taskops',
data: {
action: 'getTasks',
},
success: res => {
const tasks = res.result.data
this.setData({
todoTasks: tasks.filter(task => task.status === 'todo'),
doingTasks: tasks.filter(task => task.status === 'doing'),
doneTasks: tasks.filter(task => task.status === 'done'),
})
},
fail: err => {
console.error('[云函数] [taskops] 调用失败', err)
}
})
},
})
components/taskcard/taskcard.wxml
```html
<!--taskcard.wxml-->
<view class="task-card" bindtap="openDetail" data-id="{{task._id}}">
<view class="task-card-title">{{task.title}}</view>
<view class="task-card-meta">
<text>{{task.assignee}}</text>
<text>{{task.dueDate}}</text>
</view>
<view class="task-card-priority" style="background-color: {{task.priority === 'high' ? 'red' : task.priority === 'middle' ? 'yellow' : 'green'}}"></view>
</view>
components/taskcard/taskcard.js
// taskcard.js
Component({
properties:
{
task:
{
type: Object
,
value:
{},
},
},
methods:
{
openDetail:
function(e)
{
const taskId
= e
.currentTarget
.dataset
.id
wx
.navigateTo({
url:
`/pages/taskdetail/taskdetail?id=${taskId}`,
})
},
}
})
cloud-functions/taskops/index.js
// 云函数入口文件
const cloud
=
require('wx-server-sdk')
cloud
.init()
const db
= cloud
.database()
const _
= db
.command
// 云函数入口函数
exports
.main
=
async
(event, context)
=>
{
const
{ action
, taskId
, taskData
}
= event
const openid
= cloud
.getWXContext().OPENID
if
(action
===
'getTasks')
{
// 获取任务列表
return
await db
.collection('tasks').where({
assignee: openid
,
}).get()
}
else
if
(action
===
'addTask')
{
// 添加任务
return
await db
.collection('tasks').add({
data:
{
...taskData
,
assignee: openid
,
createTime: db
.serverDate(),
}
})
}
else
if
(action
===
'updateTask')
{
// 更新任务
return
await db
.collection('tasks').doc(taskId
).update({
data:
{
...taskData
,
updateTime: db
.serverDate(),
},
})
}
// 其他操作...
}
pages/taskdetail/taskdetail.wxml
<!--taskdetail.wxml-->
<view class="container">
<view class="task-detail-title">{{task.title}}
</view>
<view class="task-detail-desc">{{task.description}}
</view>
<view class="task-detail-meta">
<text>负责人
: {{task.assignee}}
</text>
<text>截止时间
: {{task.dueDate}}
</text>
<text>优先级
: {{task.priority}}
</text>
</view>
<view class="task-detail-subtasks">
<view class="task-detail-subtasks-title">子任务
</view>
<view wx:for="{{task.subtasks}}" wx:key="id">
<view>{{item.title}}
</view>
<view>{{item.status}}
</view>
</view>
</view>
<view class="task-detail-comments">
<view class="task-detail-comments-title">评论
</view>
<view wx:for="{{task.comments}}" wx:key="id">
<view>{{item.author}}: {{item.content}}
</view>
</view>
<view>
<input placeholder="添加评论" bindinput="onCommentInput"></input>
<button bindtap="addComment">发送
</button>
</view>
</view>
<view class="task-detail-operations">
<button wx:if="{{task.status !== 'done'}}" bindtap="finishTask">完成任务
</button>
<button bindtap="deleteTask">删除任务
</button>
</view>
</view>
pages/taskdetail/taskdetail.js
// taskdetail.js
Page({
data:
{
taskId:
'',
task:
{},
commentInput:
'',
},
onLoad:
function(options)
{
this.setData({
taskId: options
.id
})
this.getTaskDetail()
},
getTaskDetail:
function()
{
wx
.cloud
.callFunction({
name:
'taskops',
data:
{
action:
'getTaskDetail',
taskId:
this.data
.taskId
,
},
success:
res
=>
{
this.setData({
task: res
.result
.data
,
})
},
})
},
onCommentInput:
function(e)
{
this.setData({
commentInput: e
.detail
.value
})
},
addComment:
function()
{
const comment
=
this.data
.commentInput
.trim()
if
(!comment
)
{
return
}
wx
.cloud
.callFunction({
name:
'taskops',
data:
{
action:
'addComment',
taskId:
this.data
.taskId
,
commentData:
{
content: comment
,
},
},
success:
res
=>
{
this.getTaskDetail()
this.setData({
commentInput:
''
})
},
})
},
finishTask:
function()
{
wx
.cloud
.callFunction({
name:
'taskops',
data:
{
action:
'updateTask',
taskId:
this.data
.taskId
,
taskData:
{
status:
'done',
},
},
success:
res
=>
{
this.getTaskDetail()
},
})
},
deleteTask:
function()
{
wx
.cloud
.callFunction({
name:
'taskops',
data:
{
action:
'deleteTask',
taskId:
this.data
.taskId
,
},
success:
res
=>
{
wx
.navigateBack()
},
})
},
})
pages/dutylog/dutylog.wxml
<!--dutylog.wxml-->
<view class="container
">
pages/dutylog/dutylog.js
// dutylog.js
Page({
data: {
dutyLogs: [],
},
onLoad: function() {
this.getDutyLogs()
},
getDutyLogs: function() {
wx.cloud.callFunction({
name: 'dutyops',
data: {
action: 'getDutyLogs',
},
success: res => {
this.setData({
dutyLogs: res.result.data,
})
},
})
},
exportLogs: function() {
wx.cloud.callFunction({
name: 'dutyops',
data: {
action: 'exportDutyLogs',
},
success: res => {
console.log(res.result)
const fileUrl = res.result.fileUrl
wx.downloadFile({
url: fileUrl,
success: res => {
const filePath = res.tempFilePath
wx.openDocument({
filePath: filePath,
})
},
})
},
})
},
})
cloud-functions/dutyops/index.js
// 云函数入口文件
const cloud = require('wx-server-sdk')
cloud.init()
const db = cloud.database()
const _ = db.command
const xlsx = require('node-xlsx')
const fs = require('fs')
// 云函数入口函数
exports.main = async (event, context) => {
const { action } = event
if (action === 'getDutyLogs') {
// 获取值班日志
return await db.collection('dutyLogs').get()
} else if (action === 'exportDutyLogs') {
// 导出值班日志
const logs = (await db.collection('dutyLogs').get()).data
const data = logs.map(log => [log.date, log.shift, log.onDuty, log.content])
const headers = ['日期', '班次', '值班人员', '工作内容']
const sheetData = [headers, ...data]
const sheet = xlsx.build([{name: '值班日志', data: sheetData}])
const buffer = sheet.toString('binary')
const today = new Date().toISOString().slice(0, 10)
const filename = `值班日志_${today}.xlsx`
const fileUrl = await cloud.uploadFile({
cloudPath: filename,
fileContent: Buffer.from(buffer, 'binary'),
})
return {
fileUrl: fileUrl.fileID
}
}
}
以上分别是:
- 任务详情页面的布局和逻辑,包括任务信息展示、子任务列表、评论功能、完成和删除任务等。
- 值班日志页面的布局和逻辑,包括日志列表展示和日志导出功能。
- 值班日志相关的云函数,包括获取日志列表和导出日志到Excel等。
其中值班日志的导出用到了node-xlsx库和云存储的能力,将数据导出为Excel文件并上传到云存储,返回文件地址供小程序端下载。
故障记录和文档共享的实现思路与任务和值班日志类似,这里就不再赘述。你可以参考上述代码,结合具体的数据结构和业务需求,自行实现相关功能。
除了主要的业务页面和逻辑,小程序中还有一些其他的通用组件和工具类,例如:
components/faultitem/faultitem.wxml
<!--faultitem.wxml-->
<view class="fault-item">
<view class="fault-item-time">{{fault.time}}
</view>
<view class="fault-item-desc">{{fault.description}}
</view>
<view class="fault-item-impact">影响
: {{fault.impact}}
</view>
<view class="fault-item-operations">
<button bindtap="resolveFault" data-id="{{fault._id}}">解决
</button>
</view>
</view>
utils/util.js
// util.js
const
formatTime
=
date
=>
{
const year
= date
.getFullYear()
const month
= date
.getMonth()
+
1
const day
= date
.getDate()
const hour
= date
.getHours()
const minute
= date
.getMinutes()
const second
= date
.getSeconds()
return
[year
, month
, day
].map(formatNumber
).join('/')
+
' '
+
[hour
, minute
, second
].map(formatNumber
).join(':')
}
const
formatNumber
=
n
=>
{
n
= n
.toString()
return n
[1]
? n
:
'0'
+ n
}
module
.exports
=
{
formatTime: formatTime
}
utils/auth.js
// auth.js
const app
=
getApp()
const
checkLogin
=
()
=>
{
return
new
Promise((resolve, reject)
=>
{
if
(app
.globalData
.userInfo
)
{
resolve(app
.globalData
.userInfo
)
}
else
{
wx
.login({
success:
()
=>
{
wx
.getUserInfo({
success:
res
=>
{
app
.globalData
.userInfo
= res
.userInfo
resolve(res
.userInfo
)
},
fail:
err
=>
{
reject(err
)
}
})
},
fail:
err
=>
{
reject(err
)
}
})
}
})
}
const
checkPermission
=
(scope)
=>
{
return
new
Promise((resolve, reject)
=>
{
wx
.getSetting({
success:
res
=>
{
if
(res
.authSetting
[scope
])
{
resolve()
}
else
{
wx
.authorize({
scope: scope
,
success:
()
=>
{
resolve()
},
fail:
err
=>
{
reject(err
)
}
})
}
},
fail:
err
=>
{
reject(err
)
}
})
})
}
module
.exports
=
{
checkLogin: checkLogin
,
checkPermission: checkPermission
,
}
这些工具类封装了一些通用的函数,如日期格式化、登录检查、权限检查等,可以在项目中复用。
最后,项目中还应该有一些配置文件,如:
project.config.json: 项目配置文件,包含了项目的一些元信息和设置。
sitemap.json: 配置小程序及其页面是否允许被微信索引。
以上就是一个相对完整的任务协作小程序的主要代码组成和结构,涵盖了从前端页面到后端云函数的主要功能模块的实现。你可以在此基础上进一步完善和扩展,开发出一个满足实际需求的生产级别应用。
pages/personal/personal.wxml
<!--personal.wxml-->
<view class="container">
<view class="personal-info">
<image class="personal-avatar" src="{{userInfo.avatarUrl}}"></image>
<text class="personal-nickname">{{userInfo.nickName}}
</text>
</view>
<view class="personal-stats">
<view class="personal-stats-item">
<text class="personal-stats-num">{{todoCount}}
</text>
<text class="personal-stats-label">待办任务
</text>
</view>
<view class="personal-stats-item">
<text class="personal-stats-num">{{doneCount}}
</text>
<text class="personal-stats-label">已完成任务
</text>
</view>
</view>
<view class="personal-settings">
<view class="personal-settings-item">
<text>修改头像
</text>
<button open-type="chooseAvatar" bind:chooseavatar="onChooseAvatar">选择头像
</button>
</view>
<view class="personal-settings-item">
<text>修改昵称
</text>
<input value="{{userInfo.nickName}}" bindinput="onNicknameInput"></input>
<button bindtap="updateNickname">保存
</button>
</view>
</view>
</view>
pages/personal/personal.js
// personal.js
const app
=
getApp()
Page({
data:
{
userInfo:
{},
todoCount:
0,
doneCount:
0,
},
onLoad()
{
this.setData({
userInfo: app
.globalData
.userInfo
})
this.getTaskStats()
},
getTaskStats()
{
wx
.cloud
.callFunction({
name:
'taskops',
data:
{
action:
'getTaskStats',
},
success:
res
=>
{
const
{ todoCount
, doneCount
}
= res
.result
this.setData({
todoCount
,
doneCount
,
})
},
})
},
onChooseAvatar(e)
{
const
{ avatarUrl
}
= e
.detail
this.setData({
'userInfo.avatarUrl': avatarUrl
,
})
this.updateUserInfo()
},
onNicknameInput(e)
{
this.setData({
'userInfo.nickName': e
.detail
.value
})
},
updateNickname()
{
this.updateUserInfo()
},
updateUserInfo()
{
wx
.cloud
.callFunction({
name:
'userops',
data:
{
action:
'updateUserInfo',
userInfo:
this.data
.userInfo
,
},
success:
res
=>
{
app
.globalData
.userInfo
=
this.data
.userInfo
},
})
},
})
cloud-functions/userops/index.js
// 云函数入口文件
const cloud
=
require('wx-server-sdk')
cloud
.init()
const db
= cloud
.database()
// 云函数入口函数
exports
.main
=
async
(event, context)
=>
{
const
{ action
, userInfo
}
= event
if
(action
===
'updateUserInfo')
{
const openid
= cloud
.getWXContext().OPENID
return
await db
.collection('users').where({
_openid: openid
}).update({
data: userInfo
})
}
}
services/user.js
// user.js
const app
=
getApp()
const
updateUserInfo
=
async
(userInfo)
=>
{
if
(!app
.globalData
.openid
)
{
await app
.getOpenidAsync()
}
const db
= wx
.cloud
.database()
return db
.collection('users').where({_openid: app.globalData.openid
}).update({
data: userInfo
})
}
const getUserInfo = async () => {
if (!app.globalData.openid) {
await app.getOpenidAsync()
}
const db = wx.cloud.database()
const res = await db.collection('users').where({
_openid: app.globalData.openid
}).get()
return res.data[0]
}
module.exports = {
updateUserInfo,
getUserInfo,
}
services/task.js
```javascript
// task.js
const db = wx.cloud.database()
const _ = db.command
const addTask = async (task) => {
return db.collection('tasks').add({
data: {
...task,
status: 'todo',
createTime: db.serverDate(),
}
})
}
const updateTask = async (id, task) => {
return db.collection('tasks').doc(id).update({
data: {
...task,
updateTime: db.serverDate(),
}
})
}
const deleteTask = async (id) => {
return db.collection('tasks').doc(id).remove()
}
const getTasks = async (status) => {
return db.collection('tasks').where({
status,
}).get()
}
const getTaskStats = async (openid) => {
const todoRes = await db.collection('tasks').where({
_openid: openid,
status: 'todo',
}).count()
const doneRes = await db.collection('tasks').where({
_openid: openid,
status: 'done',
}).count()
return {
todoCount: todoRes.total,
doneCount: doneRes.total,
}
}
module.exports = {
addTask,
updateTask,
deleteTask,
getTasks,
getTaskStats,
}
app.js
// app.js
App({
globalData:
{
userInfo:
null,
openid:
null,
},
onLaunch()
{
this.initCloud()
},
initCloud()
{
wx
.cloud
.init({
env:
'your-env-id',
})
},
getOpenidAsync()
{
return
new
Promise((resolve, reject)
=>
{
wx
.cloud
.callFunction({
name:
'login',
}).then(res
=>
{
this.globalData
.openid
= res
.result
.openid
resolve(res
.result
.openid
)
}).catch(err
=>
{
console
.error('getOpenidAsync error:', err
)
reject(err
)
})
})
},
})
pages/faultrecord/faultrecord.wxml
<!--faultrecord.wxml-->
<view class="container">
<view class="fault-list">
<view wx:for="{{faults}}" wx:key="id">
<faultitem fault="{{item}}"></faultitem>
</view>
</view>
<view class="fault-add">
<button bindtap="addFault">添加故障
</button>
</view>
</view>
pages/faultrecord/faultrecord.js
// faultrecord.js
const
{ getFaults
, addFault
, resolveFault
}
=
require('../../services/fault')
Page({
data:
{
faults:
[],
},
onLoad()
{
this.getFaultList()
},
async
getFaultList()
{
const faults
=
await
getFaults()
this.setData({ faults
})
},
addFault()
{
wx
.navigateTo({
url:
'/pages/faultdetail/faultdetail',
})
},
async
handleResolveFault(e)
{
const
{ id
}
= e
.detail
await
resolveFault(id
)
this.getFaultList()
},
})
pages/faultdetail/faultdetail.wxml
<!--faultdetail.wxml-->
<view class="container">
<view class="fault-detail-form">
<view class="fault-detail-form-item">
<text>故障时间
:
</text>
<picker mode="date" value="{{fault.time}}" bindchange="onTimeChange">
<view>{{fault.time}}
</view>
</picker>
</view>
<view class="fault-detail-form-item">
<text>故障描述
:
</text>
<textarea value="{{fault.description}}" bindinput="onDescInput"></textarea>
</view>
<view class="fault-detail-form-item">
<text>影响范围
:
</text>
<input value="{{fault.impact}}" bindinput="onImpactInput"></input>
</view>
</view>
<view class="fault-detail-actions">
<button bindtap="saveFault">保存
</button>
</view>
</view>
pages/faultdetail/faultdetail.js
// faultdetail.js
const
{ addFault
}
=
require('../../services/fault')
Page({
data:
{
fault:
{
time:
'',
description:
'',
impact:
'',
},
},
onLoad(options)
{
if
(options
.id
)
{
// 编辑模式
// 获取故障详情
}
else
{
// 新增模式
this.setData({
fault:
{
time:
this.formatDate(new
Date()),
description:
'',
impact:
'',
},
})
}
},
formatDate(date)
{
const year
= date
.getFullYear()
const month
= date
.getMonth()
+
1
const day
= date
.getDate()
return
`${year}-${month}-${day}`
},
onTimeChange(e)
{
this.setData({
'fault.time': e
.detail
.value
,
})
},
onDescInput(e)
{
this.setData({
'fault.description': e
.detail
.value
,
})
},
onImpactInput(e)
{
this.setData({
'fault.impact': e
.detail
.value
,
})
},
async
saveFault()
{
await
addFault(this.data
.fault
)
wx
.navigateBack()
},
})
pages/doclist/doclist.wxml
<!--doclist
.wxml-->
pages/doclist/doclist.js
```javascript
// doclist.js
const { getDocs } = require('../../services/doc')
Page({
data: {
docs: [],
},
onLoad() {
this.getDocList()
},
async getDocList() {
const docs = await getDocs()
this.setData({ docs })
},
openDoc(e) {
const { url } = e.currentTarget.dataset
wx.navigateTo({
url: `/pages/webview/webview?url=${url}`,
})
},
})
pages/webview/webview.wxml
<!--webview.wxml-->
<web-view src="{{url}}"></web-view>
pages/webview/webview.js
// webview.js
Page({
data:
{
url:
'',
},
onLoad(options)
{
const
{ url
}
= options
this.setData({ url
})
},
})
services/fault.js
// fault.js
const db
= wx
.cloud
.database()
const
addFault
=
async
(fault)
=>
{
return db
.collection('faults').add({
data:
{
...fault
,
status:
'unsolved',
createTime: db
.serverDate(),
}
})
}
const
getFaults
=
async
()
=>
{
return db
.collection('faults').orderBy('createTime',
'desc').get()
}
const
resolveFault
=
async
(id)
=>
{
return db
.collection('faults').doc(id
).update({
data:
{
status:
'resolved',
resolveTime: db
.serverDate(),
}
})
}
module
.exports
=
{
addFault
,
getFaults
,
resolveFault
,
}
services/doc.js
// doc.js
const db
= wx
.cloud
.database()
const
addDoc
=
async
(doc)
=>
{
return db
.collection('docs').add({
data:
{
...doc
,
createTime: db
.serverDate(),
updateTime: db
.serverDate(),
}
})
}
const
getDocs
=
async
()
=>
{
return db
.collection('docs').orderBy('updateTime',
'desc').get()
}
module
.exports
=
{
addDoc
,
getDocs
,
}
cloud-functions/faultops/index.js
// 云函数入口文件
const cloud
=
require('wx-server-sdk')
cloud
.init()
const db
= cloud
.database()
const _
= db
.command
// 云函数入口函数
exports
.main
=
async
(event, context)
=>
{
const
{ action
, faultId
, faultData
}
= event
if
(action
===
'addFault')
{
return
await db
.collection('faults').add({
data:
{
...faultData
,
status:
'unsolved',
createTime: db
.serverDate(),
}
})
}
else
if
(action
===
'resolveFault')
{
return
await db
.collection('faults').doc(faultId
).update({
data:
{
status:
'resolved',
resolveTime: db
.serverDate(),
}
})
}
}
cloud-functions/docops/index.js
// 云函数入口文件
const cloud
=
require('wx-server-sdk')
cloud
.init()
const db
= cloud
.database()
const _
= db
.command
// 云函数入口函数
exports.main = async (event, context) => {
const { action, docData } = event
if (action === 'addDoc') {
return await db.collection('docs').add({
data: {
...docData,
createTime: db.serverDate(),
updateTime: db.serverDate(),
}
})
}
}