任务协作小程序

这篇具有很好参考价值的文章主要介绍了任务协作小程序。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

项目名称:任务协作小程序

项目目标:开发一个基于微信小程序平台的任务协作应用,帮助团队成员更好地管理和跟踪任务,提高协作效率和质量。

功能需求:

  1. 用户管理
  • 支持微信一键登录,利用微信提供的登录能力,简化用户注册流程。
  • 用户与所属机构关联,同机构用户数据一致。
  • 个人中心允许用户查看和管理个人信息,提供头像、昵称等的修改功能。
  1. 任务看板
  • 任务看板以列表和卡片的形式展示任务,采用看板式设计,任务状态一目了然。可以拖拽移动任务卡片,便于直观地管理任务。
  • 每个任务卡片设计醒目,包括标题、负责人、截止日期等关键信息。
  • 任务卡片可以设置优先级,用不同颜色或图标表示。
  • 任务看板分为待办、进行中、已完成等多个列表,表示任务的不同状态。
  • 点击任务卡片可以查看和编辑任务详情,包括描述、子任务、附件、评论等。注意界面平滑切换,保证信息的一致性和流畅性。
  • 任务可以多层级分解为子任务,子任务完成后自动更新父任务进度,可以用进度条等形式直观展示。
  • 任务支持协作讨论和评论,可以@相关人员。
  • 所有任务操作自动记录到值班日志,注意控制权限,如任务的查看和编辑权限。
  1. 值班日志
  • 值班日志由任务操作、故障记录、手动输入三部分组成,自动归类整理汇总。
  • 字段包括但不限于日期、班次、人员、工作内容等,可以考虑允许一定程度的自定义。
  • 支持手动填写其他工作内容。
  • 可导出为格式化的 TXT 文件,文件名称格式为"值班日志_日期_班次.txt"。导出时需要鉴权,控制值班日志的查看和导出权限。
  1. 故障记录
  • 记录故障发生时间、描述、影响范围、原因等关键信息。
  • 关联到相应任务,形成闭环的故障处理流程。
  • 自动生成预防性维护任务,提高系统可靠性。
  • 关键信息自动记入值班日志,与任务、日志形成联动。
  • 提供故障统计分析功能,为运维优化提供数据支持。可利用小程序云开发的云函数和云数据库能力。
  1. 文档共享
  • 以列表形式展示共享文档。
  • 点击文档,跳转到腾讯文档等在线文档页面。
  • 注意文档的鉴权,只有相关人员可查看、编辑文档。
  1. 通知提醒
  • 新任务分配时,自动推送小程序通知,提醒相关用户。
  • 可以考虑提供多种提醒方式,如微信订阅消息、邮件、短信等。

交互设计建议:

任务看板布局清晰,可拖拽操作,便于直观管理任务。
2. 任务卡片设计醒目,关键信息一目了然,支持快速编辑。
3. 任务列表和任务详情界面平滑切换,保证信息的一致性和流畅性。
4. 界面整体布局简洁明了,突出重点信息。合理使用 tab、列表、卡片等组件。
5. 表单填写、任务操作等提供引导和及时反馈,如填写提示、完成提示、进度展示等。
6. 注意权限控制,如任务的查看和编辑权限、值班日志的查看和导出权限等。

技术建议:

  1. 采用微信小程序云开发方案,利用其提供的云函数、云存储、云数据库等能力,加速开发进程。
  2. 数据存储可以考虑 JSON 格式,便于前端解析展示。存储和获取都需要进行用户鉴权。
  3. 导出功能可由前端生成 TXT 文件,然后以二进制形式下载。后端提供数据接口支持。
  4. 评论、通知、导出等及时性要求高的功能,可以考虑合理利用缓存优化性能。
  5. 故障记录、统计分析等计算量大的功能,可以利用小程序云开发的云函数和云数据库能力。
  6. 任务看板的拖拽操作需要合理控制,避免误操作。可以考虑在拖拽时添加视觉反馈,如阴影、高亮等。
  7. 任务看板的性能优化很重要,尤其是任务数量较多时。可以考虑分页加载、懒加载等技术。
  8. 离线支持可以考虑利用小程序的本地存储,定期与服务器同步数据,保证离线时也能使用基本功能。

安全与权限:

  1. 重视数据安全,涉及隐私的数据要加密存储,传输过程也要加密。
  2. 严格控制数据访问权限,如任务的查看和编辑权限、值班日志的查看和导出权限等。
  3. 用户登录时进行身份验证,保证只有合法用户才能访问数据。
  4. 定期备份数据,制定数据恢复预案,最大限度减少数据丢失风险。
  5. 编写安全代码,防范常见的 Web 攻击,如 XSS、CSRF、SQL 注入等。

其他建议:

  1. 提供完善的帮助文档和用户指南,方便用户学习和使用。
  2. 建立用户反馈渠道,收集用户意见,不断优化产品。
  3. 制定合理的开发计划和迭代策略,逐步完善功能,提高用户满意度。
  4. 注重代码质量,编写清晰、易维护的代码,必要时编写单元测试,提高代码可靠性。
  5. 密切关注小程序平台的更新和变化,及时调整开发策略,充分利用新功能。

任务协作小程序设计了如下目录结构:

│  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

    }

  }

}

以上分别是:

  1. 任务详情页面的布局和逻辑,包括任务信息展示、子任务列表、评论功能、完成和删除任务等。
  2. 值班日志页面的布局和逻辑,包括日志列表展示和日志导出功能。
  3. 值班日志相关的云函数,包括获取日志列表和导出日志到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(),
}
})
}
}
文章来源地址https://www.toymoban.com/news/detail-850283.html

到了这里,关于任务协作小程序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Python程序员Visual Studio Code指南4管理项目和协作

    Python程序员Visual Studio Code指南4管理项目和协作

    在项目上下文中管理源代码,需要能够导航和维护文件,在适当的Pytho 环境中工作,以及通过源控制维护更改。这些任务中的每一项都可以在Visual Studio Code中作为标准功能或通过安装扩展来实现。本章将在使用ChatBotAI库创建的聊天机器人应用程序中探讨管理项目的核心功能。

    2024年02月12日
    浏览(7)
  • [ChatGPT] 从 GPT-3.5 到 GPT-5 的进化之路 | ChatGPT和程序员 : 协作 or 取代

    [ChatGPT] 从 GPT-3.5 到 GPT-5 的进化之路 | ChatGPT和程序员 : 协作 or 取代

    ⭐作者介绍:大二本科网络工程专业在读,持续学习Java,努力输出优质文章 ⭐作者主页:@逐梦苍穹 ⭐如果觉得文章写的不错,欢迎点个关注一键三连😉有写的不好的地方也欢迎指正,一同进步😁 写在前面:ChatGPT官方:https://chat.openai.com/chat 任何限制次数的、功能较单一的

    2024年02月05日
    浏览(12)
  • 【网安AIGC专题10.19】论文3代码生成:ChatGPT+自协作代码生成+角色扮演(分析员、程序员、测试员)+消融实验、用于MBPP+HumanEval数据集

    【网安AIGC专题10.19】论文3代码生成:ChatGPT+自协作代码生成+角色扮演(分析员、程序员、测试员)+消融实验、用于MBPP+HumanEval数据集

    Yihong Dong∗, Xue Jiang∗, Zhi Jin†, Ge Li† (Peking University) arXiv May 2023 arXiv 2023.4.15 https://arxiv.org/pdf/2304.07590.pdf 一位不愿意透露姓名的朋友分享了Self-collaboration Code Generation via ChatGPT《基于ChatGPT的自协作代码生成》 这篇论文是chatgpt的黑盒api调用,因此没有关于模型的微调等操作,

    2024年02月03日
    浏览(15)
  • 不想使用notepad++,快使用notepad--来替换

    不想使用notepad++,快使用notepad--来替换

    相信越来越多的人已经认识到notepad++作者的可恶了,我曾经也是notepad++的使用者,当我看到它的作者一个台湾人,明目张胆的利用软件开始宣传他的错误观点后,便觉得要做些什么了。 notepad++不过是一个小软件,谈不上复杂,而且不支持mac和linux平台。我几乎每天都要使用编

    2024年02月16日
    浏览(4)
  • notepad++官网地址 https://notepad-plus-plus.org/;notepad++ 官网地址 https://notepad-plus-plus.org/

    notepad++ 官网地址 https://notepad-plus-plus.org/ 今天想进官网下载notepad++ ,却发现百度搜索官网都是出来很多乱七八糟的,就自己记录一下 notepad++官网:https://notepad-plus-plus.org/ notepad++项目主页:https://github.com/notepad-plus-plus/notepad-plus-plus/

    2024年02月11日
    浏览(6)
  • notepad++ 批量替换删除指定字符之后 或者 之前的字符,Notepad+批量替换使用大全

    notepad++ 批量替换删除指定字符之后 或者 之前的字符,Notepad+批量替换使用大全

    资源宝分享:www.httple.net 注意: 不支持多行表达式 (involving n, r, etc). 1 基本表达式 符号 解释 . 匹配任意字符,除了新一行(n)。也就是说 “.”可以匹配 r ,当文件中同时含有r and n时,会引起混乱。要匹配所有的字符,使用sS。 (…) 这个匹配一个标签区域. 这个标签可以被

    2024年02月07日
    浏览(4)
  • MacOS 任务栏程序&获取指定程序窗口信息

    MacOS 任务栏程序&获取指定程序窗口信息

    // // AppDelegate.swift // pickColor // // Created by BCZ on 2023/1/6. // import Cocoa @main class AppDelegate: NSObject, NSApplicationDelegate { let statusItem = NSStatusBar.system.statusItem(withLength: -1) @IBOutlet weak var statusMenu: NSMenu! func applicationDidFinishLaunching(_ aNotification: Notification) { // Insert code here to initialize your appli

    2024年01月17日
    浏览(8)
  • 编译程序的任务

    编译程序的任务

    编译程序是一种翻译程序,编译程序是将一种语言形式翻译成另一种语言形式。它将高级语言所写的源程序翻译成等价的机器语言或汇编语言的目标程序。 整个编译过程一般可以划分为 5 个阶段:词法分析、语法分析、语义分析及中间代码生成、中间代码优化和目标代码生成

    2024年02月09日
    浏览(1)
  • Linux程序、进程和计划任务

    Linux程序、进程和计划任务

    目录 一.程序和进程 1.程序的概念 2.进程的概念 3.线程的概念 4.单线程与多线程 5.进程的状态 二.查看进程信息相关命令: 1.ps:查看静态进程信息状态 2.top:查看动态进程排名信息 3.pgrep:查看指定进程  4.pstree:以树形结构列出进程信息  6.iostat:显示所有设备负载情况  三

    2024年01月19日
    浏览(9)
  • Notepad++ 的安装及配置

    Notepad++ 的安装及配置

    由于电脑重装了Win11系统,干脆重头开始,重新安装每一个软件~~~ 很多博客或者博主都会推荐notepad++的官网:https://notepad-plus-plus.org/  但大家亲自点开就会发现是无响应,如下图 同时,也会有很多博主直接给网盘地址下载。这里为大家介绍两种不使用官网和网盘地址的方法!

    2024年02月09日
    浏览(15)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包