running技术流程文档

2023-12-13 03:53:56

一、项目文件说明:

(注:getMyMoney无用已删除)
在这里插入图片描述

二、重要文件介绍

1.reinfo.js:位于utils文件下,该文件封装有统一的请求URL,和请求API同意封装供页面调用;调用时候需要在页面上先引入该文件,如下(index/index.js为例):

//先引入
import API from "../../utils/reinfo.js";

// 后使用的时候如下
wx.request({
  url: API.getSysConfig,//这里的API就是上面引入时候的名字,getSysConfig就是我们reinfo.js文件里封装的
  method:"get",
  success: function (res) {
  	// 调用接口成功后执行的
  }
})

2.app.js:这个是小程序的启动文件,每次小程序启动的话,必定会执行这个文件里的方法。

//onLaunch 小程序生命周期,启动就会执行
onLaunch: function () {
  var that=this;
  // 展示本地存储能力
  var openId = wx.getStorageSync('openId') || null
  // 获取用户openid、使用 Promise 
  // 这里的获取用户openid使用Promise 因为需要让index.js可以调用他来获取openid,因为index作为第一个小程序页面,也具有优先执行权,有时候会在app.js执行之前先执行,有时候会在app.js执行之后执行,所以这里使用Promise做一个异步请求,来供index.js页面调用回调获取用户数据
  const getUserOpenId = new Promise((resolve, reject) => {
    if(openId){
      console.log('缓存openid',openId)
      resolve(openId); // resolve Promise
    }else{
      // 登录code获取openid
      wx.login({
        success: function (res) {
          var code = res.code;//发送给服务器的code
            if (code) {
              wx.request({
                url: API.getSessinOpenid,
                method:"post",
                data: {
                  code: code,
                },
                header: {
                  'content-tpe': 'application/json'
                },
                success: function (res) {
                  console.log('获取到的用户openid为:',res)
                  //可以把openid保存到本地缓存,方便以后调用
                  wx.setStorageSync('openId', res.data.data);
                  // that.getUserInfoFun(res.data.data)
                  resolve(res.data.data); // resolve Promise
                },
                fail:function(res){
                  reject(err); // reject Promise
                  console.log(res)
                }
              })
            }
            else {
              console.log("获取用户登录态失败!");
            }
        },
        fail: function (error) {
        }
      })
    }
  });
   // 将 Promise 对象存储到全局数据对象中
   this.globalData.getUserOpenId = getUserOpenId;

  //  获取用户信息
  //这个获取用户信息同上意思
  const getUserInfo = new Promise((resolve, reject) => {
    wx.request({
      url: API.getUserInfo,
      method:"post",
      data: {
        openId: wx.getStorageSync('openId') || null,
      },
      success: function (res) {
        console.log('openid获取用户信息:',res)
        wx.setStorageSync('userInfo', res.data.data);
        resolve(res.data.data); // resolve Promise
      }
    })
  })
  // 将 Promise 对象存储到全局数据对象中
  this.globalData.getUserInfo = getUserInfo;
  
},

这个页面底部有个changeTabBar方法这个是自定义底部导航组件用来切换页面的公共方法
小程序组件的使用方法如下:
1.封装组件如comment\tabbar\tabbar.wxml这里就是封装了一个底部导航组件:
在这里插入图片描述
其他需要使用的页面进行引入(index/index):
wxml:


<import src="../../comment/tabbar/tabbar.wxml" />
<template is="tabbar" data="{{tabbar}}"/>

js:

//获取应用实例
const app = getApp();
Page({
/**
   * 页面的初始数据
   */
  data: {
    //底部导航栏
    tabbar: {},
  },
  //在onshow或者onload调用app下的changeTabBar方法来进行点击切换页面
  onload(){
    //调用app中的函数
    app.changeTabBar(); 
 } 
})

3.postOrder:发布订单是一个大麻烦:这里需要使用一个点击切换和滑动切换(同用户订单列表页和跑腿订单列表页)。
wxml:

<view class="navbar">
  <text wx:for="{{navbar}}" data-idx="{{index}}" class="item {{currentTab==index ? 'active' : ''}}" wx:key="unique" bindtap="navbarTap">{{item}}</text>
</view>

js:

/**
 * 页面的初始数据
 */
data: {
  navbar: ['帮我买', '帮我送', '帮我取'],
  currentTab: 0,
}


  //电机头部切换bar
  navbarTap: function (e) {
    console.log( e.currentTarget.dataset.idx)
    let initPrice = app.globalData.sysConfig.minDeliveryPrice
    // 切换的时候需要将数据清空,让用户重新输入
    let postData = {
      "commodity": "",
      "commodityCost": 0,
      "commodityWeight": 1,
      "deliveryAddress": "",
      "deliveryConcat": "",
      "deliveryPhone": "",
      "deliveryTime": "",
      "openId": "",
      "orderType": e.currentTarget.dataset.idx*1,
      "pickUpAddress": "",
      "pickUpContact": "",
      "pickUpPhone": "",
      "pickUpTime": "",
      "remark": "",
      "tipCost": 0,
      "totalCost": 0
    }
    // 设置取货时间、配送时间
    postData.deliveryTime = this.calculateFutureTime()
    if(postData.orderType == 1||postData.orderType == 2){
      postData.pickUpTime = this.calculateFutureTime()
    }
    var userInfo = wx.getStorageSync('userInfo') || {}
    postData.deliveryPhone = userInfo.phone
    // postData.orderType = e.currentTarget.dataset.idx
    this.setData({
      currentTab: e.currentTarget.dataset.idx,
      postData,
      
      multiIndex1: [0, 0], // 默认选择当天和第一个时间段
      multiIndex2: [0, 0], // 默认选择当天和第一个时间段
      multiIndex3: [0, 0], // 默认选择当天和第一个时间段
      multiIndex4: [0, 0], // 默认选择当天和第一个时间段

      price: initPrice
    })
    //全局变量
    app.globalData.currentTab = e.currentTarget.dataset.idx;
  },
  // 轮播切换,即左右滑动切换
  swiperChange: function (e) {
    let initPrice = app.globalData.sysConfig.minDeliveryPrice
    // 切换类型的话清空
    let postData = {
      "commodity": "",
      "commodityCost": 0,
      "commodityWeight": 1,
      "deliveryAddress": "",
      "deliveryConcat": "",
      "deliveryPhone": "",
      "deliveryTime": "",
      "openId": "",
      "orderType": e.detail.current*1,
      "pickUpAddress": "",
      "pickUpContact": "",
      "pickUpPhone": "",
      "pickUpTime": "",
      "remark": "",
      "tipCost": 0,
      "totalCost": 0
    }
    // 设置取货时间、配送时间
    postData.deliveryTime = this.calculateFutureTime()
    if(postData.orderType == 1||postData.orderType == 2){
      postData.pickUpTime = this.calculateFutureTime()
    }
    var userInfo = wx.getStorageSync('userInfo') || {}
    postData.deliveryPhone = userInfo.phone
    this.setData({
      currentTab: e.detail.current,
      postData,
      
      multiIndex1: [0, 0], // 默认选择当天和第一个时间段
      multiIndex2: [0, 0], // 默认选择当天和第一个时间段
      multiIndex3: [0, 0], // 默认选择当天和第一个时间段
      multiIndex4: [0, 0], // 默认选择当天和第一个时间段
      price: initPrice
    })
    //全局变量
    app.globalData.postOrderCurrentTab = e.detail.current;
  },

来实现顶部以及点击切换:在这里插入图片描述
配送时间的选择,进行一个立即配送和之后的每隔30分钟可供选择,有当天和次日,
在这里插入图片描述
wxml:

<view class="v1-item">
  <view>预计送达时间</view>
  <picker mode="multiSelector" bindcolumnchange="bindMultiPickerColumnChange" range="{{[dateRange, timeRange]}}" value="{{multiIndex1}}" data-id="1" bindchange="bindMultiPickerChange">
    <view class="picker">
      {{dateRange[multiIndex1[0]]}} {{timeRange[multiIndex1[1]]}}
    </view>
  </picker>
</view>

js:

data:{
    dateRange: ['今天', '明天'],
    timeRange: [], // 存储时间段的数组
    multiIndex1: [0, 0], // 默认选择当天和第一个时间段  帮我买:预计送达时间
    multiIndex2: [0, 0], // 默认选择当天和第一个时间段  帮我送:预计取货时间
    multiIndex3: [0, 0], // 默认选择当天和第一个时间段  帮我送:预计送达时间
    multiIndex4: [0, 0], // 默认选择当天和第一个时间段  帮我取:预计送达时间
}

  // 配送时间选择列表发生改变时候监听
  bindMultiPickerColumnChange(e){
    console.log('修改的列为', e.detail.column, ',值为', e.detail.value,e);
    if(e.detail.column == 0 && e.detail.value == 1){
      var startOfDay = new Date();
      startOfDay.setHours(0, 0, 0, 0);
      dayType = 1
      this.generateTimeRange(startOfDay)
    }
    else if(e.detail.column == 0 && e.detail.value == 0){
      dayType = 0
      this.generateTimeRange(new Date())
    }
  },
  // 计算时间选择列表
  generateTimeRange: function(now) {
    // var now = new Date();
    var hours = now.getHours();
    var minutes = now.getMinutes();
    var timeRange = [];
    
    // 生成时间段,每半个小时为一个时间段,共24小时
    for (var i = 0; i < 48; i++) {
      var hour = Math.floor(i / 2);
      var minute = (i % 2) * 30;
      
      // 格式化时间,补零操作
      var hourStr = hour < 10 ? '0' + hour : '' + hour;
      var minuteStr = minute === 0 ? '00' : '' + minute;
      
      if (hour > hours || (hour == hours && minute >= minutes)) {
        timeRange.push(hourStr + ':' + minuteStr);
      }
    }
    if(dayType == 0){
      timeRange[0] = '立即配送'
    }
    
    this.setData({
      timeRange: timeRange
    });
  },
  // 根据当前时间自动计算30分钟后的时间,并在遇到23:40时能正确计算到次日
  calculateFutureTime() {
    var currentDate = new Date();
    var futureDate = new Date(currentDate.getTime() + 30 * 60000); // 加上30分钟的毫秒数
  
    // 如果超过了当天的23:59:59,就设置到次日的00:30
    if (futureDate.getDate() > currentDate.getDate()) {
      futureDate = new Date(futureDate.getFullYear(), futureDate.getMonth(), futureDate.getDate(), 0, 30, 0);
      
      var originalDate = new Date(futureDate);
      var hour = originalDate.getHours()<10?'0'+originalDate.getHours():originalDate.getHours();
      // var minute = originalDate.getMinutes();
      var minute = originalDate.getMinutes()<10?'0'+originalDate.getMinutes():originalDate.getMinutes();
      var formattedTime = hour + ':' + minute;
      // var formattedTime = hour<10?0+hour:hour + ':' + minute;
      console.log("当前时间0000:" , currentDate);
      console.log("30分钟后的时间000:" , futureDate,formattedTime);
      return '次日 '+formattedTime;
    }
    var originalDate = new Date(futureDate);
    var hour = originalDate.getHours()<10?'0'+originalDate.getHours():originalDate.getHours();
    var minute = originalDate.getMinutes()<10?'0'+originalDate.getMinutes():originalDate.getMinutes();
    // var minute = originalDate.getMinutes();
    var formattedTime = hour + ':' + minute;
    // var formattedTime = hour<10?0+hour:hour + ':' + minute;

    console.log("当前时间111:" , currentDate);
    console.log("30分钟后的时间1111:" , futureDate,formattedTime);
    return '今天 '+formattedTime;
  },
  // 选择
  bindMultiPickerChange: function(e) {
    console.log('选择',e)
    let postData = this.data.postData
    let type = e.currentTarget.dataset.id
    console.log('这样可以吗?',this.data['multiIndex'+type])
    // 如果是立即配送自动匹配现在的30分钟后
    if(this.data.timeRange[e.detail.value[1]] == '立即配送'){
      postData.deliveryTime = this.calculateFutureTime()
    }
    if(type == 1){
      postData.deliveryTime = this.data.dateRange[this.data['multiIndex'+type][0]] +' '+ this.data.timeRange[this.data['multiIndex'+type][1]]
    }
    if(type == 2){
      postData.pickUpTime = this.data.dateRange[this.data['multiIndex'+type][0]] +' '+ this.data.timeRange[this.data['multiIndex'+type][1]]
    }
    if(type == 3){
      postData.deliveryTime = this.data.dateRange[this.data['multiIndex'+type][0]] +' '+ this.data.timeRange[this.data['multiIndex'+type][1]]
    }
    if(type == 4){
      postData.deliveryTime = this.data.dateRange[this.data['multiIndex'+type][0]] +' '+ this.data.timeRange[this.data['multiIndex'+type][1]]
    }
    
    this.setData({
      ['multiIndex'+type]: e.detail.value,
      postData,
    });
    console.log('结果》》》?',this.data['multiIndex'+type])
  },

图片上传列表
wxml:

<view class="v1">
     <!-- 图片列表 -->
     <view class="image-list">
       <block wx:for="{{images}}" wx:key="index">
         <view class="image-item">
           <image src="{{item}}" mode="aspectFill" data-src="{{item}}" bindtap="previewImage"></image>
           <view class="delete-btn" bindtap="deleteImage" data-index="{{index}}">×</view>
         </view>
       </block>
       <!-- 添加图片按钮 -->
       <view class="add-image" bindtap="chooseImage">
         <text>+</text>
       </view>
     </view>
   </view>

js:

data:{
    images: [], // 存储已选择的图片列表
}

 // 选择图片
  chooseImage() {
    let that = this;
    wx.chooseImage({
      count: 1,
      sizeType: ['original', 'compressed'],
      sourceType: ['album', 'camera'],
      success: (res) => {
        console.log('选择图片',res)
        wx.uploadFile({
          url: API.uploadImg,
          filePath: res.tempFilePaths[0],
          name: 'file',
          header: {
            "Content-Type": "multipart/form-data"
          },
          formData: {
            'type': 4 //1-表示头像,2-表示身份证,4-订单图片
          },
          success (resFile){
            let fileData = JSON.parse(resFile.data)
            console.log("文件上传接口",JSON.parse(resFile.data))
            if(fileData.code == 0){
              // 上传成功时候插入原有的数据中
              const newImages = that.data.images.concat(fileData.data);
              that.setData({
                images: newImages,
              });
            }else{
              wx.showToast({
                title: fileData.msg,
                icon: 'error'
              })
            }
          }
        })
        
      },
    });
  },

  // 预览图片
  previewImage(e) {
    const current = e.target.dataset.src;
    wx.previewImage({
      current: current,
      urls: this.data.images,
    });
  },

  // 删除图片
  deleteImage(e) {
    const index = e.target.dataset.index;
    const newImages = this.data.images;
    // 删除指定位置index的图片
    newImages.splice(index, 1);
    this.setData({
      images: newImages,
    });
  },

4.index:抢单大厅样式

//<!-- class使用三元运算符,动态设置class名称,用遍历数据,判断奇偶数来实现左右不同样式 -->
<view class="{{index%2 == 0?'v2-body-v1':'v2-body-v2'}}" wx:for="{{orderHallList}}"  bindtap="gotoOrderDetail" data-paymentStatus="{{item.paymentStatus}}" data-orderStatus="{{item.orderStatus}}" data-id="{{item.id}}" data-type="orderHall">
  <view class="{{index%2 == 0?'v2-body-v1-price':'v2-body-v2-price'}}">{{item.totalCost}}</view>
  <view class="{{index%2 == 0?'v2-body-v1-text':'v2-body-v2-text'}}">
    <image src="{{index%2 == 0?'/images/zuo.png':'/images/you.png'}}"></image>
    <text>{{item.orderType == 'BUY'?'帮我买':item.orderType == 'SEND'?'帮我送':item.orderType == 'TAKE'?'帮我取':''}}</text>
  </view>
  <view class="{{index%2 == 0?'v2-body-v1-img':'v2-body-v2-img'}}">
    <view>{{item.deliveryAddress}}</view>
    <view>{{item.deliveryTime}}</view>
  </view>
</view>

5.订单完成的评价打分
wxml:

<view class="v1-item">
  // <!-- 星星打分实现 -->
    <view style="width: 100%;line-height: 60rpx;">
      <view style="width: unset;margin-left: unset;" class='starLen' bindtap="myStarChoose">
        <block wx:for="{{starMap}}">
          <image wx:if="{{star>=index+1}}" class='star' data-star="{{index+1}}" src="../../images/start-2.png" /> 
          <image wx:if="{{star<index+1}}" class='star' data-star="{{index+1}}" src="../../images/start-1.png" />    
        </block>
      </view>
      <view class="scoreContent" style="width: unset;margin-left: unset;">{{starMap[star-1]}}</view>
    </view>
  </view>

js:

/**
   * 页面的初始数据
   */
  data: {
    star: 0,  //默认0分
    starMap: [
      '非常差',
      '差',
      '一般',
      '好',
      '非常好',
    ],
  },
  
  // 选星
  myStarChoose(e) {
    let star = parseInt(e.target.dataset.star) || 0;
    // 获取打的分
    this.setData({
      star: star,
    });
  },

管理员后台

一、项目文件说明

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

二、重要文件介绍

vue.config.js
这个文件的话主要是配置一些系统的启动配置

//修改后面的8111就可以修改项目的启动后的打开时候的端口号
const port = process.env.port || process.env.npm_config_port || 8111 // 端口
// webpack-dev-server 相关配置
  devServer: {
    host: '0.0.0.0',
    port: port,
    open: true,
    proxy: {
      [process.env.VUE_APP_BASE_API]: {
        target: `https://d51936z881.eicp.vip/`,   //代理,修改成本地如127.0.0.1:端口号
        changeOrigin: true,
        pathRewrite: {
          ['^' + process.env.VUE_APP_BASE_API]: ''
        }
      }
    },
    disableHostCheck: true
  },

src/router/index.js:路由文件


// 公共路由
export const constantRoutes = [
  {
    path: '/redirect',
    component: Layout,
    hidden: true,
    children: [
      {
        path: '/redirect/:path(.*)',
        component: () => import('@/views/redirect')
      }
    ]
  },
  {
    path: '/login',
    component: () => import('@/views/login'),
    hidden: true
  },
  {
    path: '/register',
    component: () => import('@/views/register'),
    hidden: true
  },
  {
    path: '/404',
    component: () => import('@/views/error/404'),
    hidden: true
  },
  {
    path: '/401',
    component: () => import('@/views/error/401'),
    hidden: true
  },
  // {
  //   path: '/iframe',
  //   // component: () => import('@/views/iframe/index'),
  //   component: () => import('@/components/iFrame/IframeLayout'),
  //   hidden: true
  // },
  {
    path: '/',
    component: Layout,
    redirect: 'index',
    hidden: false,
    children: [
      {
        path: 'index',
        component: () => import('@/views/index'),
        name: 'Index',
        meta: { title: '首页', icon: 'dashboard', affix: true }
      }
    ]
  },
  {
    path: '/OrderManage',
    component: Layout,
    redirect: 'index',
    hidden: false,
    children: [
      {
        name:'OrderList',
        path: '/OrderManage/OrderList',
        component: () => import('@/views/OrderManage/OrderList/index.vue'),
        meta: { title: '订单列表', affix: true }
      }
    ]
  },
  {
    path: '/MemberManage',
    component: Layout,
    redirect: 'MemberManage',
    hidden: false,
    meta: { title: '用户管理' },
    children: [
      {
        name:'LegrunnerList',
        path: '/MemberManage/LegrunnerList',
        component: () => import('@/views/MemberManage/LegrunnerList/index.vue'),
        meta: { title: '跑腿员列表' }
      },
      {
        name:'ApplyList',
        path: '/MemberManage/ApplyList',
        component: () => import('@/views/MemberManage/ApplyList/index'),
        meta: { title: '申请列表' }
      },
      {
        name:'MenberList',
        path: '/MemberManage/menberList',
        component: () => import('@/views/MemberManage/MemberList/index'),
        meta: { title: '会员列表' }
      },
    ]
  },
  {
    path: '/systemManage',
    component: Layout,
    redirect: 'systemManage',
    hidden: false,
    meta: { title: '系统管理' },
    children: [
      {
        name:'SystemConfig',
        path: '/MemberManage/systemConfig',
        component: () => import('@/views/system/config/index'),
        meta: { title: '系统配置' }
      },
    ]
  }
]

混入的使用:混入是在一个文件中写页面的script标签里的统一数据、方法
在页面中使用:

import {ListMixin} from "@/mixins/ListMixin";
export default {
	mixins: [ListMixin],
}

就能在页面中使用到混入文件的方法或数据
例如src/views/MemberManage/ApplyList/index.vue页面中需要dictData的数据,我们有很多页面需要这个,就将本地数据在ListMixin混入中引入


const dictData = require('@/utils/dictData')
data() {
  return {
    // 本地字典
    dictData:dictData,
 }

然后页面中使用


<el-table-column
  label="审核状态"
  align="center"
  v-if="colData['auditStatus'] == undefined || colData['auditStatus']"
>
  <template slot-scope="scope">
    {{ auditStatusMap.get(scope.row.auditStatus) }}
  </template>
</el-table-column>
//使用map过滤数据
computed: {
    auditStatusMap() {
      const map = new Map();
      this.dictData.auditStatus.forEach(status => {
        map.set(status.value, status.label);
      });
      return map;
    }
  },

vue的写法其实跟小程序很像主要得去看vue的文档https://cn.vuejs.org/v2/guide/具体项目中有不明白的再提问吧。因为这个也不好说哪个难,只要vue有了解应该就能明白的。
这里列举这几个比较难的流程,如果后面对哪些模块的流程有不明白的可以再提出来

文章来源:https://blog.csdn.net/XujiRe/article/details/134868145
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。