E-commerce Order Management System Implementation

Overview

Preventing Page Scaling

To disable user zoom functionality:

<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">

State Management for Categories

mapActions Helper Funciton

methods: {
  ...mapActions({
    fetchCategoryList: 'fetchCategoryList'
  }),
}

// Invoke using this.fetchCategoryList()

Namespacing

When multiple modules have identical action names, implement namespaced: true during store definition to avoid conflicts. Call actions using module prefixes like /category/fetchProductList.

Order Submission Process

The system retrieves product IDs, user IDs, and item quantities to create orders. It also handles cart ID removal upon order creation.

Implementation involves clearing selection data before capturing selected items:

<template>
  <button @click="processOrder">Process Order</button>
</template>

<script>
data() {
  return {
    cartItems: [],
    selectedItems: [],
    hasSelection: false,
    selectAll: true
  }
},
methods: {
  processOrder() {
    this.selectedItems = [];
    this.cartItems.forEach(item => {
      if (item.checked) {
        this.selectedItems.push(item);
      }
    });
    console.log(this.selectedItems);
  }
}
</script>

Order-related API Endpoints

Backend Route Configuration

Configure routes in day06/myapp/routes/order.js and register in app.js.

Database Collecsion Design

Create sql/collection/orders.js:

const mongoose = require('../db.js');
const Schema = mongoose.Schema;

const orderSchema = new Schema({
  orderId: {type: String},
  userId: {type: String},
  status: {type: Number}, // 0=pending payment, 1=shipped, 2=pending review, 3=all orders
  items: {type: Array}
});

module.exports = mongoose.model('Order', orderSchema);

Order Creation Endpoint

router.get('/create', (req, res, next) => {
  const orderData = JSON.parse(req.query.data);
  const userId = req.query.userId;
  const orderId = 'order_' + uuid.v1();
  const orderItems = [];
  
  orderData.forEach(item => {
    orderItems.push({
      productId: item.productId,
      image: item.image,
      name: item.name,
      price: parseFloat(item.price),
      quantity: parseInt(item.quantity)
    });
  });
  
  sql.insert(Order, {
    orderId: orderId,
    userId: userId,
    status: 0,
    items: orderItems
  }).then(() => {
    res.json({
      code: '200',
      message: 'Order created successfully'
    });
  });
});

Cart Cleanup After Order Creation

Use Promise.all to handle asynchronous loop operations:

router.get('/create', (req, res, next) => {
  const orderData = JSON.parse(req.query.data);
  const userId = req.query.userId;
  const orderId = 'order_' + uuid.v1();
  const orderItems = [];
  
  orderData.forEach(item => {
    orderItems.push({
      productId: item.productId,
      image: item.image,
      name: item.name,
      price: parseFloat(item.price),
      quantity: parseInt(item.quantity)
    });
  });
  
  sql.insert(Order, {
    orderId: orderId,
    userId: userId,
    status: 0,
    items: orderItems
  }).then(() => {
    const deletionPromises = orderData.map(item => {
      return sql.delete(Cart, { cartId: item.cartId });
    });
    
    return Promise.all(deletionPromises);
  }).then(() => {
    res.json({
      code: '200',
      message: 'Order created',
      data: {
        orderId: orderId
      }
    });
  });
});

Order Retrieval

router.get('/', (req, res, next) => {
  const status = req.query.status;
  let query = { userId: req.query.userId, orderId: req.query.orderId };
  
  if (status) {
    query.status = status;
  }
  
  sql.find(Order, query, { _id: 0 }).then(data => {
    res.json({
      code: '200',
      message: 'Order list retrieved',
      length: data.length,
      data: data
    });
  });
});

Order Interface Implementation

Cart Page Order Submission

In views/cart/index.vue:

processOrder() {
  this.selectedItems = [];
  this.cartItems.forEach(item => {
    if (item.checked) {
      this.selectedItems.push(item);
    }
  });
  
  if (this.selectedItems.length === 0) {
    Toast('Please select items first');
    return;
  }
  
  axios.get('/order/create?data=' + JSON.stringify(this.selectedItems) + '&userId=' + localStorage.getItem('userId')).then(response => {
    console.log('order response', response.data);
    this.$router.push('/order?orderId=' + response.data.data.orderId);
  });
}

Order Display Page

In views/order/index.vue:

Basic structure and JavaScript implementation:

import axios from '@/utils/request';

export default {
  data() {
    return {
      orderItems: []
    }
  },
  created() {
    console.log(this.$route.query);
    const userId = localStorage.getItem('userId');
    
    axios.get('/order?userId=' + userId + '&orderId=' + this.$route.query.orderId).then(response => {
      console.log('order data', response.data);
      this.orderItems = response.data.data[0].items;
    });
  }
}

Confirmation Page Requirements

The confirmation page requires recipient name, contact information, delivery address, and notes.

Database Update

Modify sql/collection/orders.js:

const mongoose = require('../db.js');
const Schema = mongoose.Schema;

const orderSchema = new Schema({
  orderId: {type: String},
  userId: {type: String},
  status: {type: Number},
  recipientName: {type: String},
  phone: {type: String},
  deliveryAddress: {type: String},
  notes: {type: String},
  items: {type: Array}
});

module.exports = mongoose.model('Order', orderSchema);

Order Creation Endpoint Update

Update routes/order.js:

router.get('/create', (req, res, next) => {
  const orderData = JSON.parse(req.query.data);
  const userId = req.query.userId;
  const orderId = 'order_' + uuid.v1();
  const orderItems = [];
  
  orderData.forEach(item => {
    orderItems.push({
      productId: item.productId,
      image: item.image,
      name: item.name,
      price: parseFloat(item.price),
      quantity: parseInt(item.quantity)
    });
  });
  
  sql.insert(Order, {
    orderId: orderId,
    userId: userId,
    status: 0,
    recipientName: '',
    phone: '',
    deliveryAddress: '',
    notes: '',
    items: orderItems
  }).then(() => {
    const deletionPromises = orderData.map(item => {
      return sql.delete(Cart, { cartId: item.cartId });
    });
    
    return Promise.all(deletionPromises);
  }).then(() => {
    res.json({
      code: '200',
      message: 'Order created',
      data: {
        orderId: orderId
      }
    });
  });
});

Address Management System

Implement routing in routes/address.js, collection in sql/collection/addresses.js, and registration in app.js.

Address Collection Schema

Create sql/collection/addresses.js:

const mongoose = require('../db.js');
const Schema = mongoose.Schema;

const addressSchema = new Schema({
  addressId: {type: String},
  userId: {type: String},
  name: {type: String},
  telephone: {type: String},
  fullAddress: {type: String},
  isDefault: {type: Number} // 1=default, 0=not default
});

module.exports = mongoose.model('Address', addressSchema);

Backend Address Creation Route

router.post('/create', (req, res, next) => {
  let { userId, name, telephone, fullAddress, isDefault } = req.body;
  isDefault = isDefault * 1 || 0;
  const addressId = 'address_' + uuid.v1();
  
  sql.insert(Address, { userId, name, telephone, fullAddress, isDefault, addressId }).then(() => {
    res.json({
      code: '200',
      message: 'Address added successfully'
    });
  });
});

Frontend Address Creation Interface

Create views/address/create.vue and configure in router/index.js:

<template>
  <div class="container">
    <header class="page-header">Add Address</header>
    <div class="main-content">
      <van-address-edit
        :area-list="areaData"
        show-postal
        show-delete
        show-set-default
        show-search-result
        :search-result="searchResults"
        area-columns-placeholder="['Select Province', 'Select City', 'Select District']"
        @save="handleSave"
        @delete="handleDelete"
        @change-detail="handleChangeDetail"
      />
    </div>
  </div>
</template>

<script>
import Vue from 'vue'
import { AddressEdit, Toast } from 'vant'
import cityData from '@/utils/city'
Vue.use(AddressEdit)

export default {
  data() {
    return {
      areaData: cityData,
      searchResults: []
    }
  },
  methods: {
    handleSave(content) {
      console.log(content);
      Toast('Saved');
    },
    handleDelete() {
      Toast('Deleted');
    },
    handleChangeDetail(val) {
    }
  }
}
</script>

<style lang="scss" scoped>
</style>

Address Submission

handleSave(content) {
  console.log(content);
  axios.post('/address/create', {
    userId: localStorage.getItem('userId'),
    name: content.name,
    telephone: content.telephone,
    fullAddress: content.province + content.city + content.district + content.detailAddress,
    isDefault: content.isDefault
  }).then(() => {
    Toast('Address saved successfully');
  });
},

Default Address and List Retrieval

router.get('/', (req, res, next) => {
  const { userId, isDefault } = req.query;
  const defaultFlag = isDefault * 1 || 0;
  
  sql.find(Address, { userId, isDefault: defaultFlag }, { _id: 0 }).then(data => {
    if (data.length === 0) {
      res.json({
        code: '30000',
        message: 'No default address found'
      });
    } else {
      res.json({
        code: '200',
        message: 'Addresses retrieved',
        data: data
      });
    }
  });
});

Order Confirmation Page Address Display

<template>
  <div>
    <ul v-if="hasDefaultAddress">
      <li v-for="item in addressList" :key="item.addressId">
        {{ item.name }} - {{ item.telephone }} - {{ item.fullAddress }}
      </li>
    </ul>
    <div v-else>No default address
      <router-link to="/createAddress">Add Address</router-link>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      orderItems: [],
      addressList: [],
      hasDefaultAddress: false
    }
  },
  created() {
    console.log(this.$route.query);
    const userId = localStorage.getItem('userId');
    
    axios.get('/order?userId=' + userId + '&orderId=' + this.$route.query.orderId).then(response => {
      console.log('order data', response.data.data[0].items);
      this.orderItems = response.data.data[0].items;
    });
    
    axios.get('/address?userId=' + userId + '&isDefault=1').then(response => {
      console.log('addresses', response.data.data);
      if (response.data.code === '30000') {
        this.hasDefaultAddress = false;
      } else {
        this.hasDefaultAddress = true;
        this.addressList = response.data.data;
      }
    });
  }
}
</script>

Tags: E-commerce order-management vuejs mongodb api-integration

Posted on Sun, 10 May 2026 23:29:23 +0000 by gacon