Bladeren bron

feat 订单申请页面

wzh 4 maanden geleden
bovenliggende
commit
8b15928e17
2 gewijzigde bestanden met toevoegingen van 750 en 0 verwijderingen
  1. 322 0
      pages/cjx/hexiao/jxs/add_order.vue
  2. 428 0
      pages/cjx/hexiao/jxs/order.vue

+ 322 - 0
pages/cjx/hexiao/jxs/add_order.vue

@@ -0,0 +1,322 @@
+<template>
+  <view class="page-container">
+    <view class="card-item">
+      <view class="card-header">
+        <view class="card-title">收货信息</view>
+      </view>
+      <view class="card-body form-body">
+        <view class="form-item">
+          <text class="form-label">收货人</text>
+          <input
+              class="form-input"
+              v-model="shippingAddress.name"
+              placeholder="请输入收货人姓名"
+              placeholder-class="placeholder"
+          />
+        </view>
+        <view class="form-item">
+          <text class="form-label">联系方式</text>
+          <input
+              class="form-input"
+              type="number"
+              maxlength="11"
+              v-model="shippingAddress.phone"
+              placeholder="请输入手机号码"
+              placeholder-class="placeholder"
+          />
+        </view>
+        <view class="form-item no-border">
+          <text class="form-label">收货地址</text>
+          <input
+              class="form-input"
+              v-model="shippingAddress.fullAddress"
+              placeholder="请输入详细收货地址"
+              placeholder-class="placeholder"
+          />
+        </view>
+      </view>
+    </view>
+
+    <view class="card-item">
+      <view class="card-header">
+        <view class="card-title">商品信息</view>
+      </view>
+      <view class="card-body product-list">
+        <view class="product-item" v-for="(item, index) in productList" :key="item.id">
+          <view class="product-info">
+            <text class="product-index">{{ index + 1 }}.</text>
+            <text class="product-name">{{ item.name_ }}</text>
+          </view>
+          <uni-number-box max="500" v-model="item.count"></uni-number-box>
+
+        </view>
+      </view>
+    </view>
+
+    <view class="card-item">
+      <view class="card-header">
+        <view class="card-title">订单信息</view>
+      </view>
+      <view class="card-body">
+        <view class="remark-label">订单备注</view>
+        <textarea
+            class="remark-textarea"
+            v-model="remarks"
+            placeholder="请输入备注信息"
+            placeholder-class="placeholder"
+        />
+      </view>
+    </view>
+
+    <view class="footer-submit">
+      <button class="submit-btn" @click="submitOrder">提交订单</button>
+    </view>
+  </view>
+</template>
+
+<script>
+import {getProductList,addDealerOrder,getOrderDetail,editDealerOrder} from "@/api/hexiao";
+
+export default {
+  data() {
+    return {
+      id:0,
+      // 收货地址信息,初始为空
+      shippingAddress: {
+        name: '',
+        phone: '',
+        fullAddress: ''
+      },
+      // 商品列表
+      productList: [
+
+      ],
+      // 订单备注
+      remarks: '',
+    };
+  },
+  onLoad(opt){
+    getProductList().then(res=>{
+      this.productList = res.data;
+    })
+    this.id = opt.id;
+    if(this.id>0){
+      getOrderDetail(this.id).then(res=>{
+       let data = res.data;
+       this.shippingAddress.name = data.delivery.receiverName;
+        this.shippingAddress.phone = data.delivery.receiverPhone;
+        this.shippingAddress.fullAddress = data.delivery.address;
+
+        let items = data.items;
+        for (let i = 0; i < items.length; i++) {
+          let item = items[i];
+          let product = this.productList.find(p => p.type_ === item.productId);
+          if (product) {
+            product.count = item.quantity;
+          }
+        }
+        this.remarks = data.remark;
+      })
+    }
+  },
+  methods: {
+    // 提交订单
+    submitOrder() {
+        // 1. 数据校验 (此部分保持不变)
+        if (!this.shippingAddress.name) {
+          return uni.showToast({ title: '请输入收货人', icon: 'none' });
+        }
+        if (!/^1[3-9]\d{9}$/.test(this.shippingAddress.phone)) {
+          return uni.showToast({ title: '请输入正确的手机号', icon: 'none' });
+        }
+        if (!this.shippingAddress.fullAddress) {
+          return uni.showToast({ title: '请输入收货地址', icon: 'none' });
+        }
+
+        const items = [];
+        for (let i = 0; i < this.productList.length; i++) {
+          let item = this.productList[i];
+          if(!item.count){
+            continue;
+          }
+          items.push({
+            productId: item.type_, // 键名从 id 改为 productId
+            quantity: item.count
+          })
+        }
+        if(items.length === 0){
+          return uni.showToast({ title: '请至少选择一件商品', icon: 'none' });
+        }
+        // 2. 【核心改动】按照您指定的格式组合提交数据
+        const finalData = {
+          // 备注信息,键名为 remark
+          remark: this.remarks,
+          // 收货信息,键名为 delivery,是一个对象
+          delivery: {
+            receiverName: this.shippingAddress.name,
+            receiverPhone: this.shippingAddress.phone,
+            address: this.shippingAddress.fullAddress
+          },
+          // 商品列表,键名为 items,是一个数组
+          items: items
+        };
+      uni.showLoading({ title: '正在提交...' });
+      if(this.id>0){
+        finalData.orderId = this.id;
+        editDealerOrder(finalData).then(res=>{
+          if(res.data){
+            uni.showToast({ title: '订单提交成功', icon: 'success' });
+          }
+          uni.hideLoading();
+
+          setTimeout(() => uni.reLaunch({url:"/pages/cjx/hexiao/jxs/order"}), 1500);
+        })
+      }else{
+        addDealerOrder(finalData).then(res=>{
+          if(res.data){
+            uni.showToast({ title: '订单提交成功', icon: 'success' });
+          }
+          uni.hideLoading();
+
+          setTimeout(() => uni.reLaunch({url:"/pages/cjx/hexiao/jxs/order"}), 1500);
+        })
+      }
+
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.page-container {
+  min-height: 100vh;
+  background: linear-gradient(to bottom, #e4efff, #f5f6fa 60%);
+  padding: 30rpx;
+  box-sizing: border-box;
+  padding-bottom: 180rpx;
+}
+
+.card-item {
+  background-color: #ffffff;
+  border-radius: 20rpx;
+  padding: 30rpx;
+  margin-bottom: 30rpx;
+  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
+  position: relative;
+
+  &::before {
+    content: '';
+    position: absolute;
+    left: 0;
+    top: 35rpx;
+    width: 8rpx;
+    height: 30rpx;
+    background-color: #3c82f8;
+    border-radius: 0 4rpx 4rpx 0;
+  }
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding-bottom: 10rpx; // 缩小header和body间距
+  .card-title {
+    font-size: 32rpx;
+    font-weight: bold;
+  }
+}
+
+.card-body {
+  padding-top: 10rpx;
+  &.form-body {
+    padding-top: 0;
+  }
+}
+
+// 新增:表单项样式
+.form-item {
+  display: flex;
+  flex-direction: column;
+  padding: 20rpx 0;
+  border-bottom: 1rpx solid #f5f5f5;
+
+  &.no-border {
+    border-bottom: none;
+  }
+
+  .form-label {
+    font-size: 28rpx;
+    color: #666;
+  }
+  .form-input {
+    font-size: 30rpx;
+    color: #333;
+    padding-top: 15rpx;
+  }
+  .placeholder {
+    color: #c0c4cc;
+  }
+}
+
+.product-list {
+  border-top: 1rpx solid #f5f5f5;
+  .product-item {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 20rpx 0;
+
+    .product-info {
+      display: flex;
+      align-items: center;
+      .product-index {
+        font-size: 28rpx;
+        color: #999;
+        margin-right: 15rpx;
+      }
+      .product-name {
+        font-size: 30rpx;
+        font-weight: 500;
+      }
+    }
+  }
+}
+
+.remark-label {
+  font-size: 28rpx;
+  color: #666;
+}
+.remark-textarea {
+  margin-top: 20rpx;
+  width: 100%;
+  font-size: 30rpx;
+  background-color: #f5f6fa;
+  padding: 20rpx;
+  box-sizing: border-box;
+  border-radius: 10rpx;
+  height: 150rpx;
+}
+
+.footer-submit {
+  position: fixed;
+  left: 0;
+  bottom: 0;
+  width: 100%;
+  padding: 20rpx 30rpx;
+  background-color: #f5f6fa;
+  box-sizing: border-box;
+  padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
+  padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
+  z-index: 100;
+}
+.submit-btn {
+  background-color: #3c82f8;
+  color: #ffffff;
+  border-radius: 50rpx;
+  font-size: 32rpx;
+  height: 90rpx;
+  line-height: 90rpx;
+  &::after { border: none; }
+}
+</style>

+ 428 - 0
pages/cjx/hexiao/jxs/order.vue

@@ -0,0 +1,428 @@
+<template>
+  <view class="page-container">
+    <view class="sticky-header">
+      <view class="search-wrapper">
+        <view class="query">
+          <u-row customStyle="margin-bottom: 10px" gutter="20">
+            <u-col span="9">
+              <u--input
+                  @focus="timeShow = true"
+                  v-model="startTimeXd"
+                  placeholder="开始日期 ~ 结束日期"
+                  prefixIcon="calendar"
+                  prefixIconStyle="font-size: 22px;color: #909399"
+                  @clear="handleSearch"
+              ></u--input>
+            </u-col>
+            <u-col span="3">
+              <view class="query-btn" @click="clearSearch">
+                <view class="query-btn-text">清空</view>
+              </view>
+            </u-col>
+          </u-row>
+        </view>
+      </view>
+      <view class="tabs-wrapper">
+        <view
+            v-for="tab in tabs"
+            :key="tab.key"
+            class="tab-item"
+            :class="{ 'active': currentTab === tab.id }"
+            @click="changeTab(tab.id)"
+        >
+          {{ tab.name }}
+        </view>
+      </view>
+    </view>
+
+    <scroll-view class="list-container" scroll-y="true" @scrolltolower="loadMore">
+      <view v-if="recordList.length === 0 && loadStatus !== 'loading'" class="empty-list">
+        <text>暂无相关记录</text>
+      </view>
+
+      <view v-for="record in recordList" :key="record.orderNo" class="record-card">
+        <view class="card-header">
+          <uni-icons type="paperclip" size="20" color="#3c82f8"></uni-icons>
+          <text class="record-id" @click="detail(record.orderId)" style="text-decoration: underline">{{ record.orderNo }}</text>
+          <view class="status-badge pending" v-if="record.status === 0">
+            {{ getStatusText(record.status) }}
+          </view>
+          <view class="status-badge" style="background-color: #F5975F"  v-if="record.status === 1">
+            {{ getStatusText(record.status) }}
+          </view>
+          <view class="status-badge verified" style="background-color: #CB7EE0" v-if="record.status === 2">
+            {{ getStatusText(record.status) }}
+          </view>
+          <view class="status-badge verified" style="background-color: #54CFAB" v-if="record.status === 3">
+            {{ getStatusText(record.status) }}
+          </view>
+
+          <view class="status-badge"  style="background-color: #959AB0" v-if="record.status === 4">
+            {{ getStatusText(record.status) }}
+          </view>
+        </view>
+
+        <view class="card-body">
+          <view class="detail-row">
+            <text class="detail-label">申请时间</text>
+            <text class="detail-value">{{ record.createTime }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">包含商品总数</text>
+            <text class="detail-value">{{ record.productTypeCount }}</text>
+          </view>
+          <view class="detail-row product-item" v-for="(item, index) in record.items" :key="index">
+            <text class="detail-label">{{ item.productName }}</text>
+            <text class="detail-value">{{ item.quantity }}</text>
+          </view>
+
+
+
+        </view>
+
+      </view>
+
+      <uni-load-more :status="loadStatus"></uni-load-more>
+    </scroll-view>
+    <view class="fixed-footer">
+      <button class="add-btn" @click="addNewOrder">新增订单</button>
+    </view>
+    <u-calendar @close="timeShow = false" :show="timeShow" :mode="mode" @confirm="confirm"></u-calendar>
+    <CustomTabbar :current="1"/>
+  </view>
+
+</template>
+
+<script>
+import {queryJxsAddRecord,doCommitToJxs,doCommitToChang} from "@/api/hexiao";
+import CustomTabbar from '@/components/cjx/tabbar_hexiao_jxs.vue';
+export default {
+  components: {
+    CustomTabbar,
+  },
+  data() {
+    return {
+      startTime: '',
+      endTime: '',
+      timeShow: false,
+      startTimeXd:"",
+      mode: 'range',
+      searchQuery: '',
+      tabs: [
+        { name: '全部', key: 'all' ,id:-1 },
+        { name: '待审核', key: 'daishenhe',id: 0 },
+        { name: '已驳回', key: 'yibohui',id: 4 },
+        { name: '生产中', key: 'shengchanzhong',id: 1 },
+        { name: '已发货', key: 'yifahuo',id: 2 },
+        { name: '已完成', key: 'yiwancheng', id: 3},
+      ],
+      currentTab: -1,
+      recordList: [],
+      pagination: { page: 1, limit: 10 },
+      loadStatus: 'more', // 'more', 'loading', 'noMore'
+      isLoading: false,
+    };
+  },
+  onLoad() {
+    this.fetchRecords(true);
+  },
+  onPullDownRefresh() {
+    this.fetchRecords(true);
+  },
+  methods: {
+    addNewOrder(){
+      uni.navigateTo({ url: `/pages/cjx/hexiao/jxs/add_order` });
+    },
+    confirm(e) {
+      this.startTime = e[0];
+      this.endTime = e[e.length-1];
+      this.startTimeXd = e[0]+' ~ '+e[e.length-1];
+      if(!this.show){
+        this.handleSearch()
+      }
+      this.timeShow = false;
+
+    },
+    getStatusClass(status){
+      const statusMap = {
+        1: 'pending',
+        2: 'verifying',
+        3: 'verified'
+      };
+      return statusMap[status] || '';
+    },
+    getStatusText(status) {
+      const statusMap = {
+        0: '待审核',
+        1: '生产中',
+        2: '已发货',
+        3: '已完成',
+        4: '已驳回'
+      };
+      return statusMap[status] || '未知';
+    },
+    changeTab(tabKey) {
+      if (this.currentTab === tabKey) return;
+      this.currentTab = tabKey;
+      this.fetchRecords(true); // 切换tab时重新加载数据
+    },
+    async fetchRecords(isRefresh = false) {
+      if (this.isLoading || (this.loadStatus === 'noMore' && !isRefresh)) {
+        return;
+      }
+      if (isRefresh) {
+        this.pagination.page = 1;
+        this.recordList = [];
+        this.loadStatus = 'more';
+      }
+      this.isLoading = true;
+      this.loadStatus = 'loading';
+
+
+      let data = {};
+      if(this.currentTab !== -1){
+        data.status = this.currentTab;
+      }
+      data.startTime = this.startTime;
+      data.endTime = this.endTime;
+      data.pageIndex = this.pagination.page
+      data.pageSize = this.pagination.limit
+      queryJxsAddRecord(data).then(res=>{
+        let finalData = res.data.records;
+        if(!finalData){
+          finalData = [];
+        }
+        if (finalData.length > 0) {
+          this.recordList = [...this.recordList, ...finalData];
+          this.pagination.page++;
+          this.loadStatus = 'more';
+        } else {
+          this.loadStatus = 'noMore';
+        }
+        this.isLoading = false;
+        uni.stopPullDownRefresh();
+      });
+
+
+
+    },
+    detail(id){
+      uni.navigateTo({ url: `/pages/cjx/hexiao/jxs/order_detail?id=`+id });
+    },
+    loadMore() {
+      this.fetchRecords();
+    },
+    clearSearch(){
+      this.startTime = "";
+      this.endTime = "";
+      this.startTimeXd = "";
+      this.handleSearch()
+    },
+    handleSearch() {
+      this.fetchRecords(true);
+    },
+    verify(id,orderNo) {
+      uni.showModal({
+        title: '提示',
+        content: `确认核销订单 ${orderNo} 吗?`,
+        success: (res) => {
+          if (res.confirm) {
+            doCommitToChang(id).then(res=>{
+              if(res.code === 0){
+                this.fetchRecords(true);
+                uni.showToast({ title: '核销成功' });
+              }else{
+                uni.showToast({ title: '核销失败' });
+              }
+
+            });
+          }
+        }
+      });
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.page-container {
+  display: flex;
+  flex-direction: column;
+  height: 100vh;
+  background-color: #f5f6fa;
+}
+
+.sticky-header {
+  position: sticky;
+  top: 0;
+  z-index: 100;
+  background-color: #f5f6fa;
+}
+.search-wrapper {
+  padding: 20rpx;
+  background-color: #ffffff;
+}
+.search-bar {
+  display: flex;
+  align-items: center;
+  background-color: #f5f6fa;
+  border-radius: 50rpx;
+  padding: 0 25rpx;
+  height: 70rpx;
+}
+.search-input { flex: 1; font-size: 28rpx; margin-left: 15rpx; }
+.placeholder { color: #b0b0b0; }
+
+.tabs-wrapper {
+  display: flex;
+  background-color: #ffffff;
+  border-bottom: 1rpx solid #f0f0f0;
+  .tab-item {
+    flex: 1;
+    text-align: center;
+    padding: 25rpx 0;
+    font-size: 28rpx;
+    color: #666;
+    position: relative;
+    &.active {
+      color: #3c82f8;
+      font-weight: 500;
+      &::after {
+        content: '';
+        position: absolute;
+        bottom: 0;
+        left: 50%;
+        transform: translateX(-50%);
+        width: 60rpx;
+        height: 6rpx;
+        background-color: #3c82f8;
+        border-radius: 3rpx;
+      }
+    }
+  }
+}
+
+.list-container {
+  flex: 1;
+  height: 100%;
+}
+.empty-list { text-align: center; color: #999; padding-top: 150rpx; }
+
+.record-card {
+  background-color: #ffffff;
+  border-radius: 16rpx;
+  margin: 20rpx;
+  padding: 30rpx;
+  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
+  position: relative;
+}
+
+.card-header {
+  display: flex;
+  align-items: center;
+  padding-bottom: 20rpx;
+  border-bottom: 1rpx solid #f5f5f5;
+  .record-id {
+    font-size: 30rpx;
+    font-weight: bold;
+    color: #333;
+    margin-left: 15rpx;
+  }
+}
+
+.status-badge {
+  position: absolute;
+  top: 0;
+  right: 0;
+  padding: 8rpx 20rpx;
+  font-size: 24rpx;
+  color: #fff;
+  border-top-right-radius: 16rpx;
+  border-bottom-left-radius: 16rpx;
+
+  &.pending { background-color: #3c82f8; }
+  &.verifying { background-color: #4D7BFF; }
+  &.verified { background-color: #909399; }
+  &.bohui{ background-color: #F5975F;}
+}
+
+.card-body {
+  padding-top: 10rpx;
+}
+.detail-row {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 12rpx 0;
+  font-size: 28rpx;
+  .detail-label { color: #666; }
+  .detail-value { color: #333; }
+  &.product-item {
+    .detail-label { color: #333; }
+    .detail-value { color: #999; }
+  }
+}
+
+.card-footer {
+  display: flex;
+  justify-content: flex-end;
+  margin-top: 20rpx;
+}
+.verify-btn {
+  background-color: #3c82f8;
+  color: #fff;
+  font-size: 26rpx;
+  padding: 0 30rpx;
+  height: 60rpx;
+  line-height: 60rpx;
+  border-radius: 30rpx;
+  margin: 0;
+  &::after { border: none; }
+}
+
+.query-btn {
+  background-color: #409eff;
+  color: #fff;
+  padding: 20rpx;
+  border-radius: 10rpx;
+  height: 34rpx;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+.query-btn-icon {
+  height: 32rpx;
+  width: 32rpx;
+  background-image:
+      url("https://hyscancode.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/cjx/queryIoc.png");
+  background-size: cover;
+  background-position: center;
+  background-repeat: no-repeat;
+}
+.query-btn-text {
+  font-weight: 400;
+  font-size: 30rpx;
+  color: #F5F5F5;
+}
+.fixed-footer {
+  position: fixed;
+  bottom: 7%;
+  left: 0;
+  width: 100%;
+  background-color: #f5f6fa;
+  padding: 20rpx 30rpx;
+  padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
+  padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
+  box-sizing: border-box;
+  z-index: 100;
+}
+.add-btn {
+  background-color: #3c82f8;
+  color: white;
+  border-radius: 50rpx;
+  font-size: 32rpx;
+  height: 90rpx;
+  line-height: 90rpx;
+  &::after { border: none; }
+}
+</style>