3 Achegas b7e1199c7d ... 95a5d8611a

Autor SHA1 Mensaxe Data
  maliang 95a5d8611a fix:修改 hai 4 semanas
  maliang 519c6175d4 feat:pda流程、复核任务、货物录入 hai 1 mes
  maliang 3421b93feb feat:新增页面 hai 1 mes

+ 12 - 0
common/request/apis/aduit.js

@@ -0,0 +1,12 @@
+//复核任务列表
+export const reviewTaskList = (params, config = { custom: { auth: true } }) => {
+  return uni.$u.http.post(
+    `/pda/reviewTaskList?currentPage=${params.currentPage}&pageSize=${params.pageSize}`,
+    params,
+    config
+  );
+};
+//设置复核任务状态
+export const setReviewTask = (params, config = { custom: { auth: true } }) => {
+  return uni.$u.http.post(`/pda/setReviewTask`, params, config);
+};

+ 12 - 0
common/request/apis/goodsEnter.js

@@ -0,0 +1,12 @@
+//货物录入列表
+export const goodsInputList = (params, config = { custom: { auth: true } }) => {
+  return uni.$u.http.post(
+    `/pda/goodsInputList?currentPage=${params.currentPage}&pageSize=${params.pageSize}`,
+    params,
+    config
+  );
+};
+//货物信息录入保存
+export const goodsSave = (params, config = { custom: { auth: true } }) => {
+  return uni.$u.http.post(`/pda/goodsSave`, params, config);
+};

+ 3 - 1
common/request/apis/index.js

@@ -7,4 +7,6 @@ export const selectVersion = (params, config) => uni.$u.http.get(`/pda/selectVer
 // 下载apk包
 export const downloadApk = (params, config = {custom: { auth: false }}) => uni.$u.http.post(`/pda/downloadApk`, params, config)
 
-
+// 获取用户消息列表
+export const getMsgList = (params, config = { custom: { auth: true } }) =>
+  uni.$u.http.get(`/pda/getMsgList`, { params, config });

+ 4 - 0
common/request/apis/purchase.js

@@ -43,3 +43,7 @@ export const depotSpinnerList = (
   data,
   config = { custom: { auth: true } }
 ) => uni.$u.http.get(`/pda/depotSpinnerList`, { data, config });
+
+// 根据upc获取sku
+export const getSkuByUpc = (data, config = { custom: { auth: true } }) =>
+  uni.$u.http.get(`/pda/getSkuByUpc`, { data, config });

+ 158 - 0
components/audit-reject/audit-reject.vue

@@ -0,0 +1,158 @@
+<template>
+  <u-popup
+    :show="show"
+    mode="center"
+    @close="close"
+    @open="open"
+    :round="10"
+    :closeOnClickOverlay="false"
+    :safeAreaInsetBottom="false"
+    width="580rpx"
+  >
+    <view class="location-edit-popup">
+      <view class="popup-header">
+        <text class="popup-title">驳回复核任务</text>
+        <u-icon name="close" size="20" @click="close"></u-icon>
+      </view>
+
+      <u-form
+        :model="formData"
+        labelPosition="top"
+        labelWidth="100%"
+        :borderBottom="false"
+        ref="uForm"
+        :rules="rules"
+      >
+        <u-form-item
+          label="请输入驳回原因"
+          required
+          prop="reason"
+          :borderBottom="false"
+        >
+          <u--textarea
+            v-model="formData.reason"
+            placeholder="请输入"
+            :maxlength="100"
+            count
+          ></u--textarea>
+        </u-form-item>
+      </u-form>
+
+      <view class="btn-group">
+        <u-button
+          class="btn cancel-btn"
+          :plain="true"
+          shape="square"
+          @click="onCancel"
+          >取消</u-button
+        >
+        <u-button
+          class="btn confirm-btn"
+          type="primary"
+          shape="square"
+          @click="onConfirm"
+          >确认</u-button
+        >
+      </view>
+    </view>
+  </u-popup>
+</template>
+
+<script>
+export default {
+  name: "RejectPopup",
+  props: {
+    show: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  data() {
+    return {
+      formData: {
+        reason: "",
+      },
+      rules: {
+        reason: {
+          type: "string",
+          required: true,
+          message: "请输入驳回原因",
+          trigger: ["blur", "change"],
+        },
+      },
+    };
+  },
+  watch: {},
+  methods: {
+    close() {
+      this.$emit("update:show", false);
+    },
+    open() {
+      this.formData = {
+        reason: "",
+      };
+    },
+    onCancel() {
+      this.close();
+      this.$emit("cancel");
+    },
+    onConfirm() {
+      this.$refs.uForm
+        .validate()
+        .then((res) => {
+          this.$emit("ok", this.formData.reason);
+        })
+        .catch((errors) => {});
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.location-edit-popup {
+  padding: 30rpx;
+  width: 580rpx;
+
+  .popup-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 30rpx;
+
+    .popup-title {
+      font-size: 36rpx;
+      font-weight: 500;
+      color: #333333;
+    }
+  }
+
+  .mt-20 {
+    margin-top: 20rpx;
+  }
+
+  .btn-group {
+    display: flex;
+    justify-content: space-between;
+    margin-top: 40rpx;
+
+    .btn {
+      flex: 1;
+      height: 88rpx;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-size: 32rpx;
+
+      &.cancel-btn {
+        margin-right: 20rpx;
+        color: #666666;
+        border-color: #dddddd;
+      }
+
+      &.confirm-btn {
+        background-color: #2979ff;
+      }
+    }
+  }
+}
+</style>

+ 135 - 0
components/good-card/good-card.vue

@@ -0,0 +1,135 @@
+<template>
+  <view class="good-card">
+    <view @click="clickItem">
+      <view class="good-base">
+        <u-image
+          :src="goodImg"
+          width="128rpx"
+          height="128rpx"
+          class="good-img"
+        ></u-image>
+        <view class="ss-m-l-16">
+          <view class="good-base-name-box">
+            <view
+              :class="['good-base-name', { 'has-status': $slots.status }]"
+              >{{ goodName }}</view
+            >
+            <view class="good-status" v-if="$slots.status">
+              <slot name="status"></slot>
+            </view>
+          </view>
+          <view class="good-base-txm"
+            >{{ goodDesTitle }}:{{ goodDesValue }}</view
+          >
+        </view>
+      </view>
+      <gridForm
+        :columns="columns"
+        :formData="item"
+        @handleClickField="handleClickField"
+      ></gridForm>
+    </view>
+
+    <slot></slot>
+    <u-divider></u-divider>
+    <slot name="action"></slot>
+  </view>
+</template>
+
+<script>
+import gridForm from "@/components/grid-form/grid-form.vue";
+
+export default {
+  components: {
+    gridForm,
+  },
+  props: {
+    // 货物图片
+    goodImg: {
+      type: String,
+      default: "",
+    },
+    // 货物名称
+    goodName: {
+      type: String,
+      default: "",
+    },
+    goodDesTitle: {
+      type: String,
+      default: "SKU",
+    },
+    // 货物额外信息
+    goodDesValue: {
+      type: String,
+      default: "",
+    },
+    // 货物信息
+    item: {
+      type: Object,
+      default: () => {},
+    },
+    columns: {
+      type: Array,
+      default: () => [],
+    },
+  },
+  methods: {
+    handleClickField(key, formData) {
+      this.$emit("handleClickField", key, formData);
+    },
+    clickItem() {
+      this.$emit("clickItem", { ...this.item });
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.good-card {
+  .good-base {
+    display: flex;
+    align-items: center;
+    padding: 0 24rpx;
+    position: relative;
+
+    &-name-box {
+      display: flex;
+    }
+    &-name {
+      flex: 1;
+      max-width: 520rpx;
+      overflow: hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+      color: #333;
+      font-family: "PingFang SC";
+      font-size: 28rpx;
+      font-weight: 500;
+      margin-bottom: 16rpx;
+
+      &.has-status {
+        padding-right: 140rpx;
+      }
+    }
+    &-txm {
+      color: #999;
+      font-family: "PingFang SC";
+      font-size: 28rpx;
+      font-weight: 400;
+      word-break: break-all;
+    }
+    .good-status {
+      position: absolute;
+      right: 20rpx;
+      width: 120rpx;
+      height: 44rpx;
+      border-radius: 8rpx;
+      font-family: "PingFang SC";
+      font-weight: 400;
+      font-size: 22rpx;
+      line-height: 44rpx;
+      text-align: center;
+    }
+  }
+}
+</style>

+ 1 - 1
components/good-item/good-item.vue

@@ -10,7 +10,7 @@
           ></u-image>
           <view class="ss-m-l-16">
             <view class="good-msg-name">{{ item.materialName }}</view>
-            <view class="good-msg-txm">条形码:{{ item.barCode }}</view>
+            <view class="good-msg-txm">SKU:{{ item.sku }}</view>
           </view>
         </view>
         <view class="good-cont">

+ 82 - 0
components/grid-form/grid-form.vue

@@ -0,0 +1,82 @@
+<template>
+  <view class="grid-from">
+    <view
+      class="grid-from-item"
+      v-for="(col, index) in _columns"
+      :key="index"
+      @click.stop="handleClickField(col.key)"
+    >
+      <view class="grid-from-item-label">{{ col.title }}</view>
+      <view class="grid-from-item-value">{{ getFieldValue(col) }}</view>
+    </view>
+  </view>
+</template>
+
+<script>
+export default {
+  props: {
+    /**
+     * title: 标题
+     * key: key值
+     * formatter: 格式化函数
+     * isShow: 显/隐函数
+     */
+    columns: {
+      type: Array,
+      default: () => [],
+    },
+    formData: {
+      type: Object,
+      default: () => {},
+    },
+  },
+  computed: {
+    _columns() {
+      return this.columns.filter((col) => {
+        if (col.isShow && col.isShow instanceof Function) {
+          return col.isShow(col.key, { ...this.formData }, col);
+        }
+        return true;
+      });
+    },
+  },
+  methods: {
+    /**
+     * 点击事件
+     * @param {String} key 字段名
+     */
+    handleClickField(key) {
+      this.$emit("handleClickField", key, { ...this.formData });
+    },
+    getFieldValue(col) {
+      const formData = { ...this.formData };
+      if (col.formatter && col.formatter instanceof Function) {
+        return col.formatter(col.key, formData, col);
+      }
+      return formData[col.key] || "-";
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.grid-from {
+  display: grid;
+  grid-template-columns: 33% 33% 33%;
+  padding: 0 24rpx;
+  &-item {
+    font-family: "PingFang SC";
+    font-weight: 400;
+    margin-top: 24rpx;
+    &-label {
+      color: #999;
+      font-size: 24rpx;
+      margin-bottom: 16rpx;
+    }
+    &-value {
+      color: #000;
+      font-size: 28rpx;
+    }
+  }
+}
+</style>

+ 128 - 0
components/task-card/task-card.vue

@@ -0,0 +1,128 @@
+<template>
+  <view class="task-card">
+    <view class="task-card-flex">
+      <view
+        v-for="(col, index) in _columns"
+        class="task-col"
+        :key="index"
+        :style="getColStyle(col)"
+        @click.stop="handleClickField(col.key)"
+      >
+        <view class="task-col-label" :style="getColLabelStyle(col)"
+          >{{ col.title }}:</view
+        >
+        <view class="task-col-value" :style="getColValueStyle(col)">{{
+          getFieldValue(col)
+        }}</view>
+      </view>
+    </view>
+    <view class="task-card-right-top" v-if="$slots.rightTop">
+      <slot name="rightTop"></slot>
+    </view>
+    <u-divider></u-divider>
+    <!-- 操作区域 -->
+    <slot name="action"></slot>
+  </view>
+</template>
+
+<script>
+export default {
+  props: {
+    /**
+     * title: 标题
+     * key: key值
+     * formatter: 格式化函数
+     * isShow: 显/隐函数
+     * span: 列, 12|24
+     */
+    columns: {
+      type: Array,
+      default: () => [],
+    },
+    formData: {
+      type: Object,
+      default: () => {},
+    },
+  },
+  computed: {
+    _columns() {
+      return this.columns.filter((col) => {
+        if (col.isShow && col.isShow instanceof Function) {
+          return col.isShow(col.key, { ...this.formData }, col);
+        }
+        return true;
+      });
+    },
+  },
+  data() {
+    return {};
+  },
+  methods: {
+    /**
+     * 点击事件
+     * @param {String} key 字段名
+     */
+    handleClickField(key) {
+      this.$emit("handleClickField", key, { ...this.formData });
+    },
+    getColStyle(col) {
+      if (col.span) {
+        return { width: `${(col.span / 24) * 100}%` };
+      }
+      return { width: "100%" };
+    },
+    getColLabelStyle(col) {
+      return col.titleStyle || {};
+    },
+    getColValueStyle(col) {
+      return col.valueStyle || {};
+    },
+    getFieldValue(col) {
+      const formData = { ...this.formData };
+      if (col.formatter && col.formatter instanceof Function) {
+        return col.formatter(col.key, formData, col);
+      }
+      return formData[col.key] || "-";
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.task-card {
+  width: 100%;
+  background-color: #fff;
+  border-radius: 16rpx;
+  padding: 24rpx 24rpx 0;
+  margin-bottom: 24rpx;
+  position: relative;
+
+  .task-card-right-top {
+    position: absolute;
+    right: 24rpx;
+    top: 36rpx;
+  }
+
+  .task-card-flex {
+    width: 100%;
+    display: flex;
+    flex-wrap: wrap;
+  }
+
+  .task-col {
+    display: flex;
+    align-items: center;
+    color: #666;
+    font-family: "PingFang SC";
+    font-size: 28rpx;
+    font-weight: 400;
+    margin-top: 16rpx;
+
+    &-value {
+      overflow: hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+    }
+  }
+}
+</style>

+ 183 - 169
components/task-item/task-item.vue

@@ -1,176 +1,190 @@
 <template>
-	<view class="task-item">
-		<view @click="detailClick">
-			<view class="task-head">
-				<view class="sn-box">单据编号:{{item.number}}</view>
-				<view v-if="type == 'caigou'">
-					<view class="tips tips-red" v-if="item.status == 1">待入库</view>
-					<view class="tips tips-greed" v-if="item.status == 2">已入库</view>
-					<view class="tips tips-yellow" v-if="item.status == 4">入库中</view>
-				</view>
-				<view v-else>
-					<view class="tips tips-red" v-if="item.status == 1">待拣货</view>
-					<view class="tips tips-greed" v-if="item.status == 2">已拣货</view>
-					<view class="tips tips-yellow" v-if="item.status == 4">拣货中</view>
-				</view>
-			</view>
-			<view class="task-line" v-if="type == 'caigou'">
-				<view>供应商:</view>
-				<view>{{item.supplierName}}</view>
-			</view>
-			<view class="task-line" v-else>
-			<view>客户名称:</view>
-			<view>{{item.supplierName}}</view>
-			</view>
-			<view class="task-line">
-				<view>单据日期:</view>
-				<view>{{item.createTime}}</view>
-			</view>
-			<view class="task-line">
-				<view class="task-line2">
-					<view>货物总数:</view>
-					<view class="task-num">{{item.goodsQuantity}}件</view>
-				</view>
-				<view class="task-line2">
-					<view>货物种类:</view>
-					<view class="task-num">{{item.goodsTypeCount || 0}}种</view>
-				</view>
-			</view>
-		</view>
-		<view class="task-bottom">
-			<view v-if="type == 'caigou'">
-				<view class="btn btn-1" v-if="item.status == 1 || item.status == 4" @click="toStorage">去入库</view>
-				<view class="btn btn-2" v-else @click="toDetail">详情</view>
-			</view>
-			<view v-else>
-				<view class="btn btn-1" v-if="item.status == 1 || item.status == 4" @click="toStorage">去出库</view>
-				<view class="btn btn-2" v-else @click="toDetail">详情</view>
-			</view>
-		</view>
-	</view>
+  <view class="task-item">
+    <view @click="detailClick">
+      <view class="task-head">
+        <view class="sn-box">单据编号:{{ item.number }}</view>
+        <view v-if="type == 'caigou'">
+          <view class="tips tips-red" v-if="item.status == 1">待入库</view>
+          <view class="tips tips-red" v-if="item.status == 6">待复核</view>
+          <view class="tips tips-red" v-if="item.status == 7">复核驳回</view>
+          <view class="tips tips-greed" v-if="item.status == 3">部分入库</view>
+          <view class="tips tips-greed" v-if="item.status == 2">已入库</view>
+          <view class="tips tips-yellow" v-if="item.status == 4">入库中</view>
+        </view>
+        <view v-else>
+          <view class="tips tips-red" v-if="item.status == 1">待拣货</view>
+          <view class="tips tips-red" v-if="item.status == 6">待复核</view>
+          <view class="tips tips-red" v-if="item.status == 7">复核驳回</view>
+          <view class="tips tips-greed" v-if="item.status == 3">部分拣货</view>
+          <view class="tips tips-greed" v-if="item.status == 2">已拣货</view>
+          <view class="tips tips-yellow" v-if="item.status == 4">拣货中</view>
+        </view>
+      </view>
+      <view class="task-line" v-if="type == 'caigou'">
+        <view>供应商:</view>
+        <view>{{ item.supplierName }}</view>
+      </view>
+      <view class="task-line" v-else>
+        <view>客户名称:</view>
+        <view>{{ item.supplierName }}</view>
+      </view>
+      <view class="task-line">
+        <view>单据日期:</view>
+        <view>{{ item.createTime }}</view>
+      </view>
+      <view class="task-line">
+        <view class="task-line2">
+          <view>货物总数:</view>
+          <view class="task-num">{{ item.goodsQuantity }}件</view>
+        </view>
+        <view class="task-line2">
+          <view>货物种类:</view>
+          <view class="task-num">{{ item.goodsTypeCount || 0 }}种</view>
+        </view>
+      </view>
+    </view>
+    <view class="task-bottom">
+      <view v-if="type == 'caigou'">
+        <view
+          class="btn btn-1"
+          v-if="item.status == 1 || item.status == 4 || item.status == 7"
+          @click="toStorage"
+          >去入库</view
+        >
+        <view class="btn btn-2" v-else @click="toDetail">详情</view>
+      </view>
+      <view v-else>
+        <view
+          class="btn btn-1"
+          v-if="item.status == 1 || item.status == 4 || item.status == 7"
+          @click="toStorage"
+          >去出库</view
+        >
+        <view class="btn btn-2" v-else @click="toDetail">详情</view>
+      </view>
+    </view>
+  </view>
 </template>
 
 <script>
-	export default{
-		props:{
-			item:{
-				type:Object,
-				default:()=>{}
-			},
-			type: {
-				type:String,
-				default:''
-			}
-		},
-		data() {
-			return{
-				
-			}
-		},
-		methods:{
-			toStorage() {
-				this.$emit('toStorage',this.item)
-			},
-			toDetail() {
-				this.$emit('toDetail',this.item)
-			},
-			detailClick() {
-				if(this.item.status == 1 || this.item.status == 4) {
-					this.toStorage()
-				}else {
-					this.toDetail()
-				}
-			}
-		}
-	}
+export default {
+  props: {
+    item: {
+      type: Object,
+      default: () => {},
+    },
+    type: {
+      type: String,
+      default: "",
+    },
+  },
+  data() {
+    return {};
+  },
+  methods: {
+    toStorage() {
+      this.$emit("toStorage", this.item);
+    },
+    toDetail() {
+      this.$emit("toDetail", this.item);
+    },
+    detailClick() {
+      if (this.item.status == 1 || this.item.status == 4) {
+        this.toStorage();
+      } else {
+        this.toDetail();
+      }
+    },
+  },
+};
 </script>
 
 <style lang="scss" scoped>
-	.task-item {
-		width: 100%;
-		background-color: #fff;
-		border-radius: 16rpx;
-		padding: 24rpx 24rpx 0;
-		margin-bottom: 24rpx;
-		.task-head {
-			display: flex;
-			align-items: center;
-			justify-content: space-between;
-			.sn-box {
-				color: #333;
-				font-family: "PingFang SC";
-				font-size: 28rpx;
-				font-weight: 500;
-			}
-			.tips {
-				font-family: "PingFang SC";
-				font-size: 22rpx;
-				font-weight: 400;
-				width: 120rpx;
-				height: 44rpx;
-				border-radius: 8rpx;
-				display: flex;
-				align-items: center;
-				justify-content: center;
-			}
-			.tips-red {
-				color: #FF3B1D;
-				background: rgba(255, 59, 29, 0.20);
-			}
-			.tips-greed {
-				color: #00B97B;
-				background: rgba(0, 185, 123, 0.20);
-			}
-			.tips-yellow {
-				color: #F57701;
-				background: rgba(245, 151, 1, 0.20);
-			}
-		}
-	
-		.task-line {
-			display: flex;
-			align-items: center;
-			color: #666;
-			font-family: "PingFang SC";
-			font-size: 28rpx;
-			font-weight: 400;
-			margin-top: 16rpx;
-		}
-		.task-line2 {
-			width: 50%;
-			display: flex;
-			align-items: center;
-			.task-num {
-				color: #0256FF;;
-			}
-		}
-	
-		.task-bottom {
-			border-top: 1px solid #F0F0F0;
-			margin-top: 32rpx;
-			height: 104rpx;
-			display: flex;
-			align-items: center;
-			justify-content: flex-end;
-			.btn {
-				width: 144rpx;
-				height: 56rpx;
-				border-radius: 8rpx;
-				font-size: 28rpx;
-				display: flex;
-				align-items: center;
-				justify-content: center;
-				font-family: "PingFang SC";
-			}
-			.btn-1 {
-				background: #0256FF;
-				color: #FFF;
-			}
-			.btn-2 {
-				border: 1px solid #0256FF;
-				background: rgba(2, 86, 255, 0.20);
-				color: #0256FF;
-			}
-		}
-	}
-</style>
+.task-item {
+  width: 100%;
+  background-color: #fff;
+  border-radius: 16rpx;
+  padding: 24rpx 24rpx 0;
+  margin-bottom: 24rpx;
+  .task-head {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    .sn-box {
+      color: #333;
+      font-family: "PingFang SC";
+      font-size: 28rpx;
+      font-weight: 500;
+    }
+    .tips {
+      font-family: "PingFang SC";
+      font-size: 22rpx;
+      font-weight: 400;
+      width: 120rpx;
+      height: 44rpx;
+      border-radius: 8rpx;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+    }
+    .tips-red {
+      color: #ff3b1d;
+      background: rgba(255, 59, 29, 0.2);
+    }
+    .tips-greed {
+      color: #00b97b;
+      background: rgba(0, 185, 123, 0.2);
+    }
+    .tips-yellow {
+      color: #f57701;
+      background: rgba(245, 151, 1, 0.2);
+    }
+  }
+
+  .task-line {
+    display: flex;
+    align-items: center;
+    color: #666;
+    font-family: "PingFang SC";
+    font-size: 28rpx;
+    font-weight: 400;
+    margin-top: 16rpx;
+  }
+  .task-line2 {
+    width: 50%;
+    display: flex;
+    align-items: center;
+    .task-num {
+      color: #0256ff;
+    }
+  }
+
+  .task-bottom {
+    border-top: 1px solid #f0f0f0;
+    margin-top: 32rpx;
+    height: 104rpx;
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    .btn {
+      width: 144rpx;
+      height: 56rpx;
+      border-radius: 8rpx;
+      font-size: 28rpx;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-family: "PingFang SC";
+    }
+    .btn-1 {
+      background: #0256ff;
+      color: #fff;
+    }
+    .btn-2 {
+      border: 1px solid #0256ff;
+      background: rgba(2, 86, 255, 0.2);
+      color: #0256ff;
+    }
+  }
+}
+</style>

+ 2 - 2
manifest.json

@@ -2,8 +2,8 @@
     "name" : "pdaApp",
     "appid" : "__UNI__7E491C0",
     "description" : "pdaApp",
-    "versionName" : "1.0.3",
-    "versionCode" : 103,
+    "versionName" : "1.0.4",
+    "versionCode" : 104,
     "transformPx" : false,
     /* 5+App特有相关 */
     "app-plus" : {

+ 34 - 1
pages.json

@@ -47,7 +47,12 @@
     {
       "path": "pages/index/notice-page",
       "style": {
-        "navigationBarTitleText": ""
+        "navigationBarTitleText": "",
+        "enablePullDownRefresh": true,
+        "onReachBottomDistance": 50,
+        "app-plus": {
+          "bounce": "none"
+        }
       }
     },
     {
@@ -107,6 +112,34 @@
           "bounce": "none"
         }
       }
+    },
+    {
+      "path": "pages/goods-enter/index",
+      "style": {
+        "navigationBarTitleText": "",
+        "enablePullDownRefresh": true,
+        "onReachBottomDistance": 50,
+        "app-plus": {
+          "bounce": "none"
+        }
+      }
+    },
+    {
+      "path": "pages/goods-enter/addGood",
+      "style": {
+        "navigationBarTitleText": ""
+      }
+    },
+    {
+      "path": "pages/audit-task/index",
+      "style": {
+        "navigationBarTitleText": "",
+        "enablePullDownRefresh": true,
+        "onReachBottomDistance": 50,
+        "app-plus": {
+          "bounce": "none"
+        }
+      }
     }
   ],
   /* 分包预载配置 */

+ 541 - 0
pages/audit-task/index.vue

@@ -0,0 +1,541 @@
+<template>
+  <view class="picking-task-page">
+    <u-navbar
+      height="40px"
+      title="复核任务"
+      bgColor="#F0F6FB"
+      autoBack
+      placeholder
+    >
+      <view class="u-nav-slot depot-label" slot="right">
+        <view class="name">{{ curDepotName }}</view>
+      </view>
+    </u-navbar>
+    <view class="container_main">
+      <u-sticky :offsetTop="offsetTop" bgColor="#F0F6FB">
+        <view class="search-box">
+          <u-search
+            placeholder="请输入单据编号"
+            bgColor="#fff"
+            shape="square"
+            v-model="query.number"
+            :showAction="false"
+            @search="searchClick"
+            @clear="searchClick"
+          ></u-search>
+          <view class="flex_box" @click="scanCode">
+            <view class="scan-text">扫描单据二维码</view>
+            <view class="scan-icon">
+              <image src="@/static/image/scan-icon.png" mode=""></image>
+            </view>
+          </view>
+        </view>
+        <view class="type-box flex_box">
+          <view class="type-item" @click="tabClick(1)">
+            <view class="type-val">{{ type1 }}</view>
+            <u-icon name="arrow-down-fill" color="#999999" size="12"></u-icon>
+          </view>
+          <view class="type-item" @click="tabClick(2)">
+            <view class="type-val">{{ type2 }}</view>
+            <u-icon name="arrow-down-fill" color="#999999" size="12"></u-icon>
+          </view>
+        </view>
+      </u-sticky>
+      <view class="task-cont">
+        <block v-for="(item, i) in list" :key="`${item.id}-${item.status}`">
+          <task-card
+            :columns="taskColumns"
+            :formData="item"
+            @handleClickField="handleClickField"
+          >
+            <!-- 状态 -->
+            <view slot="rightTop">
+              <u-tag
+                v-if="item.status == 6"
+                text="待复核"
+                plain
+                borderColor="rgba(255, 59, 29, 0.2)"
+                color="rgba(255, 59, 29, 1)"
+                bgColor="rgba(255, 59, 29, 0.2)"
+              ></u-tag>
+              <u-tag
+                v-if="item.status == 2"
+                text="复核通过"
+                plain
+                borderColor="rgba(0, 185, 123, 0.2)"
+                color="rgba(0, 185, 123, 1)"
+                bgColor="rgba(0, 185, 123, 0.2)"
+              ></u-tag>
+              <u-tag
+                v-if="item.status == 7"
+                text="复核驳回"
+                plain
+                borderColor="rgba(225, 51, 15, 1)"
+                color="rgba(255, 255, 255, 1)"
+                bgColor="rgba(225, 51, 15, 1)"
+              ></u-tag>
+            </view>
+            <!-- 操作栏 -->
+            <view slot="action" class="action-box">
+              <view class="action-left-box">
+                <text v-if="item.type == '采购订单'"
+                  >入库时间: {{ item.operTime }}</text
+                >
+                <text v-if="item.type == '销售订单'"
+                  >出库时间: {{ item.operTime }}</text
+                >
+              </view>
+              <view class="task-bottom">
+                <view
+                  class="btn btn-1"
+                  @click="toAudit(item)"
+                  v-if="item.status == 6"
+                  >去复核</view
+                >
+                <view class="btn btn-2" @click="toDetail(item)" v-else
+                  >详情</view
+                >
+              </view>
+            </view>
+          </task-card>
+        </block>
+        <u-loadmore v-if="list.length > 0" :status="loadStatus" />
+        <u-empty
+          mode="data"
+          text="暂无内容"
+          marginTop="60"
+          icon="https://xiangli-erp.oss-cn-hangzhou.aliyuncs.com/APP/no-notifcations.png"
+          v-if="list.length == 0"
+        ></u-empty>
+      </view>
+    </view>
+    <!-- 状态 -->
+    <u-picker
+      :show="statusShow"
+      keyName="label"
+      :defaultIndex="defaultIndex2"
+      :columns="statusColumns"
+      @confirm="statusConfirm"
+      @cancel="statusShow = false"
+    ></u-picker>
+    <!-- 月份 -->
+    <u-picker
+      :show="dateShow"
+      :defaultIndex="defaultIndex3"
+      :columns="dateColumns"
+      @confirm="dateConfirm"
+      @cancel="dateShow = false"
+    ></u-picker>
+  </view>
+</template>
+
+<script>
+import taskCard from "@/components/task-card/task-card.vue";
+import { mapGetters } from "vuex";
+import { reviewTaskList } from "@/common/request/apis/aduit.js";
+
+export default {
+  components: {
+    taskCard,
+  },
+  data() {
+    return {
+      offsetTop: 0,
+      type1: "全部",
+      type2: "月份",
+      statusShow: false,
+      dateShow: false,
+      statusColumns: [
+        [
+          {
+            label: "全部",
+            id: "",
+          },
+          {
+            label: "待复核",
+            id: 6,
+          },
+          {
+            label: "复核通过",
+            id: 2,
+          },
+          {
+            label: "复核驳回",
+            id: 7,
+          },
+        ],
+      ],
+      dateColumns: [
+        [
+          "全年",
+          "一月",
+          "二月",
+          "三月",
+          "四月",
+          "五月",
+          "六月",
+          "七月",
+          "八月",
+          "九月",
+          "十月",
+          "十一月",
+          "十二月",
+        ],
+      ],
+      defaultIndex2: [],
+      defaultIndex3: [],
+
+      taskColumns: [
+        {
+          title: "单据编号",
+          key: "number",
+          titleStyle: {
+            color: "#333",
+            fontSize: "28rpx",
+            fontWeight: 500,
+          },
+          valueStyle: {
+            color: "#333",
+            fontSize: "28rpx",
+            fontWeight: 500,
+          },
+        },
+        {
+          title: "供应商名称",
+          key: "supplierName",
+          isShow(key, formData, col) {
+            return formData.type == "采购订单";
+          },
+        },
+        {
+          title: "客户名称",
+          key: "supplierName",
+          isShow(key, formData, col) {
+            return formData.type == "销售订单";
+          },
+        },
+        {
+          title: "单据日期",
+          key: "createTime",
+        },
+        {
+          title: "类别",
+          key: "type",
+          span: 12,
+        },
+        {
+          title: "入库人",
+          key: "operName",
+          span: 12,
+          isShow(key, formData, col) {
+            return formData.type == "采购订单";
+          },
+        },
+        {
+          title: "出库人",
+          key: "operName",
+          span: 12,
+          isShow(key, formData, col) {
+            return formData.type == "销售订单";
+          },
+        },
+        {
+          title: "货物总数",
+          key: "goodsQuantity",
+          span: 12,
+          valueStyle: {
+            color: "#0256ff",
+          },
+        },
+        {
+          title: "货物种类",
+          key: "goodsTypeCount",
+          span: 12,
+          valueStyle: {
+            color: "#0256ff",
+          },
+        },
+      ],
+      list: [],
+      currentPage: 1,
+      pageSize: 10,
+      query: {
+        beginTime: "",
+        endTime: "",
+        number: "",
+        status: "",
+      },
+      loadStatus: "loadmore", //加载前值为loadmore,加载中为loading,没有数据为nomore
+    };
+  },
+  computed: {
+    ...mapGetters(["depotInfo"]),
+    curDepotId() {
+      return this.depotInfo ? this.depotInfo.id : "";
+    },
+    curDepotName() {
+      return this.depotInfo ? this.depotInfo.depotName : "";
+    },
+  },
+  onLoad() {
+    let systemInfo = uni.getSystemInfoSync();
+    let statusBarHeight = systemInfo.statusBarHeight;
+    this.offsetTop = statusBarHeight + 40;
+    this.loadData();
+  },
+  onShow() {
+    uni.$on("scanFinish", (data) => {
+      this.query.number = data;
+      this.loadData(true);
+    });
+    if (uni.getStorageSync("auditTaskRefresh")) {
+      this.loadData(true);
+      uni.removeStorageSync("auditTaskRefresh");
+    }
+  },
+  onHide() {
+    uni.$off("scanFinish");
+  },
+  onUnload() {
+    uni.$off("scanFinish");
+  },
+  onPullDownRefresh() {
+    // 下拉刷新
+    this.onRefresh();
+  },
+  onReachBottom() {
+    // 触底加载更多
+    this.onLoadMore();
+  },
+  methods: {
+    scanCode() {
+      this.$scan.scanCode();
+    },
+    async onLoadMore() {
+      if (this.loadStatus !== "loadmore") return;
+      this.loadStatus = "loading";
+      try {
+        await this.loadData();
+      } catch (e) {
+        this.loadStatus = "loadmore";
+      }
+    },
+    async onRefresh() {
+      try {
+        await this.loadData(true);
+      } finally {
+        uni.stopPullDownRefresh();
+      }
+    },
+    async loadData(isRefresh = false) {
+      if (isRefresh) {
+        this.currentPage = 1;
+        this.list = [];
+      }
+
+      try {
+        this.loadStatus = "loading";
+        const currentPage = this.currentPage;
+        const pageSize = this.pageSize;
+        const params = {
+          currentPage,
+          pageSize,
+          ...this.query,
+          depotId: this.curDepotId,
+        };
+        console.log("params=====", params);
+        const res = await reviewTaskList(params);
+        const { rows, total } = res.data;
+        console.log("res====", res);
+        this.list = [...this.list, ...rows];
+        if (currentPage * pageSize < Number(total)) {
+          this.currentPage++;
+          this.loadStatus = "loadmore";
+        } else {
+          this.loadStatus = "nomore";
+        }
+      } catch (error) {}
+    },
+    searchClick() {
+      this.loadData(true);
+    },
+    tabClick(type) {
+      switch (type) {
+        case 1:
+          this.statusShow = true;
+          break;
+        case 2:
+          this.dateShow = true;
+          break;
+        default:
+          break;
+      }
+    },
+    statusConfirm(val) {
+      this.type1 = val.value[0].label;
+      this.query.status = val.value[0].id;
+      this.statusShow = false;
+      this.loadData(true);
+    },
+    dateConfirm(val) {
+      this.type2 = val.value[0];
+      this.dateShow = false;
+      let month = val.indexs[0];
+      this.getLastDayOfMonth(month);
+      this.loadData(true);
+    },
+    // 获取开始时间、结束时间
+    getLastDayOfMonth(month) {
+      let year = new Date().getFullYear();
+      if (month != 0) {
+        let monthStart = new Date(year, month, 0).getDate();
+        this.query.beginTime = `${year}-${month}-01`;
+        this.query.endTime = `${year}-${month}-${monthStart}`;
+      } else {
+        this.query.beginTime = "";
+        this.query.endTime = "";
+      }
+    },
+    handleClickField(key, itemData) {
+      console.log("key===", key);
+      console.log("itemData===", itemData);
+      this.toDetail(itemData);
+    },
+    // 审核
+    toAudit(val) {
+      const type = val.type;
+      switch (type) {
+        case "采购订单":
+          uni.navigateTo({
+            url: `/pages/purchase/detail?id=${val.id}&auditState=1`,
+          });
+          break;
+        case "销售订单":
+          uni.navigateTo({
+            url: `/pages/picking-task/detail?id=${val.id}&auditState=1`,
+          });
+          break;
+        default:
+          break;
+      }
+    },
+    toDetail(val) {
+      const type = val.type;
+      switch (type) {
+        case "采购订单":
+          uni.navigateTo({
+            url: `/pages/purchase/detail?id=${val.id}`,
+          });
+          break;
+        case "销售订单":
+          uni.navigateTo({
+            url: `/pages/picking-task/detail?id=${val.id}`,
+          });
+          break;
+        default:
+          break;
+      }
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.picking-task-page {
+  min-height: 100vh;
+  background: #f0f6fb;
+  .container_main {
+    .search-box {
+      display: flex;
+      align-items: center;
+      padding: 0 32rpx;
+      .scan-text {
+        color: #333;
+        font-family: "PingFang SC";
+        font-size: 24rpx;
+        font-weight: 400;
+        margin-right: 20rpx;
+        margin-left: 30rpx;
+      }
+      .scan-icon {
+        width: 36rpx;
+        height: 36rpx;
+        background-color: #fff;
+        border-radius: 50%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        image {
+          width: 24rpx;
+          height: 24rpx;
+        }
+      }
+    }
+
+    .type-box {
+      .type-item {
+        width: 50%;
+        height: 88rpx;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        .type-val {
+          color: #000;
+          font-family: "PingFang SC";
+          font-size: 28rpx;
+          font-weight: 400;
+          margin-right: 10rpx;
+        }
+      }
+    }
+
+    .task-cont {
+      padding: 0 24rpx;
+    }
+  }
+}
+
+.action-box {
+  padding-bottom: 24rpx;
+  height: 80rpx;
+  box-sizing: border-box;
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
+  width: 100%;
+}
+
+.action-left-box {
+  display: inline-flex;
+  align-items: center;
+  color: #666;
+  font-family: "PingFang SC";
+  font-size: 24rpx;
+  font-weight: 400;
+}
+.task-bottom {
+  flex: 1;
+  display: inline-flex;
+  align-items: center;
+  justify-content: flex-end;
+  .btn {
+    width: 144rpx;
+    height: 56rpx;
+    border-radius: 8rpx;
+    font-size: 28rpx;
+    line-height: 56rpx;
+    text-align: center;
+    margin-left: 12rpx;
+    font-family: "PingFang SC";
+  }
+  .btn-1 {
+    background: #0256ff;
+    color: #fff;
+  }
+  .btn-2 {
+    border: 1px solid #0256ff;
+    background: rgba(2, 86, 255, 0.2);
+    color: #0256ff;
+  }
+}
+</style>

+ 279 - 3
pages/goods-enter/addGood.vue

@@ -1,7 +1,283 @@
-<template></template>
+<template>
+  <view class="goods-page">
+    <u-navbar
+      height="40px"
+      title="新增录入"
+      bgColor="rgba(2, 86, 255, 1)"
+      autoBack
+      placeholder
+      titleStyle="color:#fff"
+      leftIconColor="#fff"
+    >
+      <view class="u-nav-slot depot-label" slot="right">
+        <view class="name" style="color: #fff">{{ curDepotName }}</view>
+      </view>
+    </u-navbar>
+    <view class="container_main">
+      <u--form
+        labelPosition="left"
+        :model="form"
+        :rules="rules"
+        ref="uForm"
+        labelWidth="90"
+      >
+        <u-form-item
+          label="货物条码"
+          prop="barCode"
+          borderBottom
+          required
+          customStyle="padding: 30rpx 0"
+        >
+          <u-input v-model="form.barCode" border="none" placeholder="请输入">
+            <u-image
+              slot="suffix"
+              src="@/static/image/scan-icon-2.png"
+              width="40rpx"
+              height="40rpx"
+              @click="scanCode"
+            ></u-image>
+          </u-input>
+        </u-form-item>
+        <u-form-item
+          label="货物名称"
+          prop="name"
+          borderBottom
+          required
+          customStyle="padding: 30rpx 0"
+        >
+          <u-input
+            v-model="form.name"
+            border="none"
+            placeholder="请输入"
+          ></u-input>
+        </u-form-item>
+        <u-form-item
+          label="规格"
+          prop="standard"
+          borderBottom
+          required
+          customStyle="padding: 30rpx 0"
+        >
+          <u-input
+            v-model="form.standard"
+            border="none"
+            placeholder="请输入"
+          ></u-input>
+        </u-form-item>
+        <u-form-item
+          label="生产日期"
+          prop="productionDate"
+          borderBottom
+          required
+          customStyle="padding: 30rpx 0"
+        >
+          <view
+            :class="['date-val', { grey: !form.productionDate }]"
+            @click="showDatePicker = true"
+            >{{ form.productionDate ? form.productionDate : "请输入" }}</view
+          >
+        </u-form-item>
+        <u-form-item
+          label="上传图片"
+          prop="imgName"
+          borderBottom
+          required
+          customStyle="padding: 30rpx 0"
+        >
+          <upload-image
+            v-model="form.imgName"
+            width="196rpx"
+            height="196rpx"
+          ></upload-image>
+        </u-form-item>
+        <u-form-item
+          label="库位"
+          prop="position"
+          borderBottom
+          required
+          customStyle="padding: 30rpx 0"
+        >
+          <u-input
+            v-model="form.position"
+            border="none"
+            placeholder="请输入"
+          ></u-input>
+        </u-form-item>
+      </u--form>
+    </view>
+    <u-datetime-picker
+      :show="showDatePicker"
+      @cancel="showDatePicker = false"
+      @confirm="confirmDate"
+      v-model="dateVal"
+      mode="date"
+    ></u-datetime-picker>
+    <!-- 新增录入-->
+    <view class="footer">
+      <u-button class="add-btn" type="primary" plain @click="save">
+        保存
+      </u-button>
+    </view>
+  </view>
+</template>
 
 <script>
-export default {};
+import { mapGetters } from "vuex";
+import { goodsSave } from "@/common/request/apis/goodsEnter.js";
+export default {
+  data() {
+    return {
+      form: {
+        barCode: "",
+        name: "",
+        standard: "",
+        imgName: "",
+        position: "",
+        productionDate: "",
+      },
+      rules: {
+        barCode: [
+          {
+            required: true,
+            message: "请输入货物条码",
+            trigger: ["blur", "change"],
+          },
+        ],
+        name: [
+          {
+            required: true,
+            message: "请输入货物名称",
+            trigger: ["blur", "change"],
+          },
+        ],
+        standard: [
+          {
+            required: true,
+            message: "请输入规格",
+            trigger: ["blur", "change"],
+          },
+        ],
+        productionDate: [
+          {
+            required: true,
+            message: "请输入生产日期",
+            trigger: ["blur", "change"],
+          },
+        ],
+        imgName: [
+          {
+            required: true,
+            message: "请上传图片",
+            trigger: ["blur", "change"],
+          },
+        ],
+        position: [
+          {
+            required: true,
+            message: "请输入库位",
+            trigger: ["blur", "change"],
+          },
+        ],
+      },
+      showDatePicker: false,
+      dateVal: "",
+    };
+  },
+  computed: {
+    ...mapGetters(["depotInfo"]),
+    curDepotId() {
+      return this.depotInfo ? this.depotInfo.id : "";
+    },
+    curDepotName() {
+      return this.depotInfo ? this.depotInfo.depotName : "";
+    },
+  },
+  onHide() {
+    uni.$off("scanFinish");
+  },
+  onShow() {
+    uni.$on("scanFinish", (data) => {
+      this.form.barCode = data;
+      this.$refs.uForm.validateField("barCode");
+    });
+  },
+  methods: {
+    scanCode() {
+      this.$scan.scanCode();
+    },
+    confirmDate(e) {
+      console.log("confirmDate====", e);
+      const { value } = e;
+      this.form.productionDate = this.$u.date(value, "yyyy-mm-dd");
+      console.log("form====", this.form);
+      this.showDatePicker = false;
+    },
+    save() {
+      this.$refs.uForm
+        .validate()
+        .then(async (res) => {
+          try {
+            const params = { ...this.form, depotId: this.curDepotId };
+            const result = await goodsSave(params);
+            console.log("result====", result);
+            if (result.code === 200) {
+              uni.$u.toast(result.msg);
+              setTimeout(() => {
+                uni.navigateBack();
+              }, 1000);
+              uni.setStorageSync("goodsEnterRefresh", true);
+            } else {
+              uni.$u.toast(result.msg);
+            }
+          } catch (error) {}
+        })
+        .catch((errors) => {});
+    },
+  },
+};
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+.goods-page {
+  min-height: 100vh;
+  background-color: #f0f6fb;
+  .container_main {
+    margin: 24rpx;
+    background-color: #fff;
+    border-radius: 16rpx;
+    padding: 24rpx;
+  }
+}
+
+.footer {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  height: 144rpx;
+  background-color: #fff;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+
+  .add-btn {
+    width: 700rpx;
+    height: 88rpx;
+    border-radius: 16rpx;
+    font-size: 36rpx;
+    font-weight: bold;
+    color: #fff;
+    background-color: #0256ff;
+    line-height: 88rpx;
+    text-align: center;
+  }
+}
+
+.date-val {
+  width: 100%;
+  font-size: 28rpx;
+}
+.grey {
+  color: #999;
+}
+</style>

+ 188 - 40
pages/goods-enter/index.vue

@@ -7,26 +7,47 @@
       autoBack
       placeholder
     >
-      <view class="u-nav-slot depot-label" slot="right" @click="stashClick">
+      <view class="u-nav-slot depot-label" slot="right">
         <view class="name">{{ curDepotName }}</view>
       </view>
     </u-navbar>
     <view class="container_main">
       <u-sticky :offsetTop="offsetTop" bgColor="#fff">
-        <view class="search-box">
-          <u-search
-            placeholder="请输入单据编号或名称"
-            shape="square"
-            v-model="query.number"
-            :showAction="false"
-            :clearabled="true"
-            @search="handleSearch"
-            @clear="handleSearch"
-          ></u-search>
+        <view class="head-box">
+          <view class="search-box">
+            <u-search
+              placeholder="货物名称或条码"
+              shape="square"
+              :showAction="false"
+              @search="handleSearch"
+              @clear="handleSearch"
+              v-model="query.keyword"
+            ></u-search>
+            <view class="scan-icon flex_box flex_row_center" @click="scanCode">
+              <image src="@/static/image/scan-icon-2.png" mode=""></image>
+            </view>
+          </view>
         </view>
       </u-sticky>
       <view class="content-box">
-        <view class="content-box-val"> </view>
+        <view class="content-list" v-if="list.length > 0">
+          <goodCard
+            v-for="(item, i) in list"
+            :key="i"
+            :goodImg="item.imgName ? item.imgName.split(',')[0] : ''"
+            :goodName="item.name"
+            :goodDesValue="item.barCode"
+            goodDesTitle="货物条码"
+            :columns="columns"
+            :item="item"
+          >
+            <view slot="status">
+              <view class="dsh" v-if="item.status == 0">待审核</view>
+              <view class="zc" v-if="item.status == 1">正常</view>
+              <view class="ybh" v-if="item.status == 8">已驳回</view>
+            </view>
+          </goodCard>
+        </view>
         <u-empty
           mode="data"
           text="暂无内容"
@@ -41,49 +62,70 @@
           @loadmore="onLoadMore"
         />
       </view>
+      <!-- 新增录入-->
+      <view class="footer">
+        <u-button class="add-btn" type="primary" plain @click="goAddGood">
+          新增录入
+        </u-button>
+      </view>
     </view>
-
-    <error-pop
-      v-model="actionPop.errorShow"
-      isCenter
-      cancelBtnText="取消"
-      confirmBtnText="确定"
-      @close="actionPop.errorShow = false"
-      @confirm="submit"
-      :content="actionPop.errorText"
-    ></error-pop>
   </view>
 </template>
 
 <script>
-import checkItem from "./components/check-item.vue";
-
-import {
-  taskStocktakingList,
-  startTask,
-  taskComplete,
-  taskStocktakingDetail,
-} from "@/common/request/apis/inventoryTask";
 import { mapGetters } from "vuex";
+import goodCard from "@/components/good-card/good-card.vue";
+import { goodsInputList } from "@/common/request/apis/goodsEnter.js";
 
 export default {
   components: {
-    checkItem,
-    errorPop,
+    goodCard,
   },
   data() {
+    const that = this;
     return {
       offsetTop: 0,
       query: {
-        number: "",
+        keyword: "",
       },
       currentPage: 1,
       pageSize: 10,
       loadStatus: "loadmore", //加载前值为loadmore,加载中为loading,没有数据为nomore
-      list: [],
 
-      // 中心仓
-      cangName: "",
+      columns: [
+        { title: "规格", key: "standard" },
+        // { title: "批次号", key: "patchNumber" },
+        {
+          title: "生产日期",
+          key: "productionDate",
+          formatter: (key, formData) => {
+            return formData.productionDate
+              ? that.$u.timeFormat(formData.productionDate, "yyyy-mm-dd")
+              : "/";
+          },
+        },
+        { title: "库位", key: "position" },
+        // {
+        //   title: "库存",
+        //   key: "inventory",
+        //   formatter: (key, formData) => {
+        //     const inventory = formData.inventory
+        //       ? (formData.inventory * 1).toFixed(0)
+        //       : "0";
+        //     return `${inventory}${formData.commodityUnit || ""}`;
+        //   },
+        // },
+        {
+          title: "录入时间",
+          key: "createTime",
+          formatter: (key, formData) => {
+            return formData.createTime
+              ? that.$u.timeFormat(formData.createTime, "yyyy-mm-dd hh:MM:ss")
+              : "/";
+          },
+        },
+      ],
+      list: [],
     };
   },
   computed: {
@@ -101,7 +143,22 @@ export default {
     this.offsetTop = statusBarHeight + 40;
     this.loadData();
   },
-  onShow() {},
+  onShow() {
+    uni.$on("scanFinish", (data) => {
+      this.query.keyword = data;
+      this.loadData(true);
+    });
+    if (uni.getStorageSync("goodsEnterRefresh")) {
+      this.loadData(true);
+      uni.removeStorageSync("goodsEnterRefresh");
+    }
+  },
+  onHide() {
+    uni.$off("scanFinish");
+  },
+  onUnload() {
+    uni.$off("scanFinish");
+  },
   onPullDownRefresh() {
     // 下拉刷新
     this.onRefresh();
@@ -111,6 +168,9 @@ export default {
     this.onLoadMore();
   },
   methods: {
+    scanCode() {
+      this.$scan.scanCode();
+    },
     async onRefresh() {
       try {
         await this.loadData(true);
@@ -144,8 +204,9 @@ export default {
           depotId: this.curDepotId,
         };
         console.log("params=====", params);
-        const res = await taskStocktakingList(params);
+        const res = await goodsInputList(params);
         const { rows, total } = res.data;
+        console.log("res====", res);
         this.list = [...this.list, ...rows];
         if (currentPage * pageSize < Number(total)) {
           this.currentPage++;
@@ -158,6 +219,11 @@ export default {
     handleSearch(value) {
       this.loadData(true);
     },
+    goAddGood() {
+      uni.navigateTo({
+        url: "/pages/goods-enter/addGood",
+      });
+    },
   },
 };
 </script>
@@ -167,6 +233,11 @@ export default {
   min-height: 100vh;
   background-color: #f0f6fb;
   .container_main {
+    .head-box {
+      background-color: #fff;
+      padding-top: 20rpx;
+      padding-bottom: 32rpx;
+    }
     .search-box {
       background-color: rgba(191, 200, 219, 0.2);
       margin: 0 32rpx;
@@ -193,9 +264,8 @@ export default {
         }
       }
     }
-
     .content-box {
-      padding: 24rpx;
+      padding: 0 24rpx 144rpx;
       &-val {
         border-radius: 16rpx 16rpx 0 0;
         overflow: hidden;
@@ -203,4 +273,82 @@ export default {
     }
   }
 }
+
+.content-list {
+  padding-top: 24rpx;
+  background-color: #fff;
+  margin-top: 24rpx;
+  border-radius: 16rpx;
+
+  .content-list-title {
+    font-family: "PingFang SC";
+    font-size: 32rpx;
+    font-style: normal;
+    font-weight: bold;
+    display: flex;
+    align-items: center;
+    position: relative;
+    padding-left: 50rpx;
+    margin-bottom: 24rpx;
+
+    &::after {
+      content: "";
+      display: block;
+      width: 6rpx;
+      height: 30rpx;
+      border-radius: 100px;
+      background: #0256ff;
+      position: absolute;
+      top: 50%;
+      left: 24rpx;
+      transform: translateY(-50%);
+    }
+
+    .content-list-title-tips {
+      color: #0256ff;
+      font-size: 24rpx;
+      font-weight: 400;
+    }
+  }
+}
+
+.dsh {
+  background-color: rgba(255, 59, 29, 0.2);
+  color: rgba(255, 59, 29, 1);
+  border-radius: 8rpx;
+}
+.zc {
+  background-color: rgba(0, 185, 123, 0.2);
+  color: rgba(0, 185, 123, 1);
+  border-radius: 8rpx;
+}
+.ybh {
+  background-color: rgba(225, 51, 15, 1);
+  color: #fff;
+  border-radius: 8rpx;
+}
+
+.footer {
+  position: fixed;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  height: 144rpx;
+  background-color: #fff;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+
+  .add-btn {
+    width: 700rpx;
+    height: 88rpx;
+    border-radius: 16rpx;
+    font-size: 36rpx;
+    font-weight: bold;
+    color: #fff;
+    background-color: #0256ff;
+    line-height: 88rpx;
+    text-align: center;
+  }
+}
 </style>

+ 12 - 5
pages/goods/detail.vue

@@ -25,7 +25,7 @@
             <text>货物条码</text>
           </view>
           <view class="info-line-value">
-            {{ goodsInfo.barCode }}
+            {{ goodsInfo.sku }}
           </view>
         </view>
         <view class="info-line">
@@ -133,7 +133,7 @@
           </view>
         </view>
         <scroll-view scroll-y class="scroll-y">
-          <view class="crk-item" v-for="(item, i) in cukList" :key="item">
+          <view class="crk-item" v-for="(item, i) in cukList" :key="item.id">
             <view class="crk-item-title">{{ item.materialName }}</view>
             <!-- <view class="crk-item-line">出库仓库:我的仓库-暂无</view> -->
             <view class="crk-item-line"
@@ -193,7 +193,7 @@ import { mapGetters } from "vuex";
 export default {
   data() {
     return {
-      navTitle: "哇哈哈AD盖",
+      navTitle: "",
       goodsId: 0, //单据id
       // materialId:0,//商品id
       crkShow: false,
@@ -236,7 +236,7 @@ export default {
     getMaterialDetail() {
       materialDetail(`${this.goodsId}/${this.curDepotId}`).then((res) => {
         if (res.code == 200) {
-          console.log(res.data, "data---------");
+          console.log("data---------", res.data);
           if (res.data.imgName && res.data.imgName.length > 0) {
             res.data.imgNameArr = res.data.imgName.split(",");
           } else {
@@ -259,6 +259,7 @@ export default {
           if (res.code == 200) {
             this.cukList = res.data.rows;
           }
+          console.log("res====", res);
           uni.hideLoading();
         })
         .catch((err) => {
@@ -282,18 +283,24 @@ export default {
 
       .info-line {
         border-bottom: 1px solid #f4f4f4;
-        min-height: 92rpx;
+        padding: 24rpx 0;
         color: #333;
         font-family: "PingFang SC";
         font-size: 28rpx;
+        line-height: 1.5;
         font-weight: 400;
         display: flex;
         align-items: center;
 
         &-label {
+          flex: 0 0 162rpx;
           width: 162rpx;
         }
 
+        &-value {
+          word-break: break-all;
+        }
+
         .must-box {
           color: #ff3b1d;
         }

+ 117 - 100
pages/index/components/notice-item.vue

@@ -1,107 +1,124 @@
 <template>
-	<view class="notice-item">
-		<view class="item-head">
-			<view class="item-head-msg">
-				<view class="image-box">
-					<u-badge type="error" :isDot="true" :show="!item.isRead" :absolute="true" :offset="[-2,-2]"></u-badge>
-					<image :src="img" mode=""></image>
-				</view>
-				<view>{{typeText}}</view>
-			</view>
-			<view class="time-box">
-				{{$u.timeFormat(item.time, 'hh:MM:ss')}}
-			</view>
-		</view>
-		<view class="item-cont">
-			您有1条新的拣货任务(单号:{{item.sn}}),请点击查看并及时处理!
-		</view>
-		<view class="item-footer">
-			<view>查看详情</view>
-			<u-icon name="arrow-right" color="#7E838D"></u-icon>
-		</view>
-	</view>
+  <view class="notice-item">
+    <view class="item-head">
+      <view class="item-head-msg">
+        <view class="image-box">
+          <u-badge
+            type="error"
+            :isDot="true"
+            :show="!item.isRead"
+            :absolute="true"
+            :offset="[-2, -2]"
+          ></u-badge>
+          <image :src="img" mode=""></image>
+        </view>
+        <view>{{ item.type }}</view>
+      </view>
+      <view class="time-box">
+        {{ $u.timeFormat(item.time, "hh:MM:ss") }}
+      </view>
+    </view>
+    <view class="item-cont">
+      您有1条新的{{ item.type }}(单号:{{
+        item.content
+      }}),请点击查看并及时处理!
+    </view>
+    <view class="item-footer" @click="toDetail">
+      <view>查看详情</view>
+      <u-icon name="arrow-right" color="#7E838D"></u-icon>
+    </view>
+  </view>
 </template>
 
 <script>
-	export default{
-		props:{
-			item:{
-				type:Object,
-				default:()=>{}
-			}
-		},
-		computed:{
-			img() {
-				let src = ""
-				if(this.item.type == 1) {
-					src = require('@/static/image/home/icon-cgrk.png')
-				}else if(this.item.type == 2) {
-					src = require('@/static/image/home/icon-chcx.png')
-				}
-				return src
-			},
-			typeText() {
-				let text = ""
-				if(this.item.type == 1) {
-					text = '采购入库'
-				}else if(this.item.type == 2) {
-					text = '存货查询'
-				}
-				return text
-			}
-		}
-	}
+export default {
+  props: {
+    item: {
+      type: Object,
+      default: () => {},
+    },
+  },
+  computed: {
+    img() {
+      const type = this.item.type;
+      let src = "";
+      switch (type) {
+        case "拣货任务":
+          src = require("@/static/image/home/icon-jhrw.png");
+          break;
+        case "采购入库":
+          src = require("@/static/image/home/icon-cgrk.png");
+          break;
+        case "盘点任务":
+          src = require("@/static/image/home/icon-pdrw.png");
+          break;
+        case "复核任务":
+          src = require("@/static/image/home/icon-fhrw.png");
+          break;
+
+        default:
+          break;
+      }
+      return src;
+    },
+  },
+  methods: {
+    toDetail() {
+      this.$emit("toDetail", { ...this.item });
+    },
+  },
+};
 </script>
 
 <style lang="scss" scoped>
-	.notice-item {
-		border-radius: 16px;
-		background: #FFF;
-		padding: 24rpx 24rpx 0;
-		margin-bottom: 24rpx;
-		.item-head {
-			display: flex;
-			align-items: center;
-			justify-content: space-between;
-			&-msg {
-				display: flex;
-				align-items: center;
-				color: #333;
-				font-family: "PingFang SC";
-				font-size: 32rpx;
-				font-weight: bold;
-				.image-box {
-					position: relative;
-					margin-right: 24rpx;
-					image {
-						width: 48rpx;
-						height: 48rpx;
-						z-index: 2;
-					}
-					::v-deep .u-badge {
-						z-index: 3;
-					}
-				}
-			}
-		}
-	
-		.item-cont {
-			color: #666;
-			font-family: "PingFang SC";
-			font-size: 28rpx;
-			font-weight: 400;
-			padding: 17rpx 0 24rpx;
-			border-bottom: 1px solid #F4F4F4;
-		}
-		.item-footer {
-			height: 88rpx;
-			display: flex;
-			align-items: center;
-			justify-content: space-between;
-			color: #333;
-			font-family: "PingFang SC";
-			font-size: 28rpx;
-			font-weight: 400;
-		}
-	}
-</style>
+.notice-item {
+  border-radius: 16px;
+  background: #fff;
+  padding: 24rpx 24rpx 0;
+  margin-bottom: 24rpx;
+  .item-head {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    &-msg {
+      display: flex;
+      align-items: center;
+      color: #333;
+      font-family: "PingFang SC";
+      font-size: 32rpx;
+      font-weight: bold;
+      .image-box {
+        position: relative;
+        margin-right: 24rpx;
+        image {
+          width: 48rpx;
+          height: 48rpx;
+          z-index: 2;
+        }
+        ::v-deep .u-badge {
+          z-index: 3;
+        }
+      }
+    }
+  }
+
+  .item-cont {
+    color: #666;
+    font-family: "PingFang SC";
+    font-size: 28rpx;
+    font-weight: 400;
+    padding: 17rpx 0 24rpx;
+    border-bottom: 1px solid #f4f4f4;
+  }
+  .item-footer {
+    height: 88rpx;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    color: #333;
+    font-family: "PingFang SC";
+    font-size: 28rpx;
+    font-weight: 400;
+  }
+}
+</style>

+ 1 - 1
pages/index/components/use-pop.vue

@@ -34,7 +34,7 @@
             <view class="use-msg-line-cont">
               <view>角色</view>
               <view class="line-value">
-                <view>{{ userInfo.position }}</view>
+                <view>{{ userInfo.roleName }}</view>
                 <!-- <u-icon name="arrow-right" color="#7E838D"></u-icon> -->
               </view>
             </view>

+ 1 - 1
pages/index/index.vue

@@ -147,7 +147,7 @@ export default {
           src: require("@/static/image/home/icon-fhrw.png"),
           text: "复核任务",
           num: 0,
-          url: "",
+          url: "/pages/audit-task/index",
         },
         {
           src: require("@/static/image/home/icon-hwlr.png"),

+ 119 - 20
pages/index/notice-page.vue

@@ -9,40 +9,136 @@
     >
     </u-navbar>
     <view class="container_main">
-      <view class="time-box"> 2025-04-03 星期四 </view>
-      <notice-item
-        v-for="(item, i) in noticeList"
-        :key="i"
-        :item="item"
-      ></notice-item>
+      <view v-for="(item, i) in list" :key="i" class="item-wrap">
+        <view class="time-box">{{ item.date }}</view>
+        <notice-item
+          v-for="child in item.msgList"
+          :key="child.id"
+          :item="child"
+          @toDetail="toDetail"
+        ></notice-item>
+      </view>
+      <!-- 加载更多 -->
+      <u-loadmore
+        v-if="list.length > 0"
+        :status="loadStatus"
+        @loadmore="onLoadMore"
+      />
+      <u-empty
+        mode="data"
+        text="暂无内容"
+        marginTop="60"
+        icon="https://xiangli-erp.oss-cn-hangzhou.aliyuncs.com/APP/no-notifcations.png"
+        v-if="list.length == 0"
+      ></u-empty>
     </view>
   </view>
 </template>
 
 <script>
 import noticeItem from "./components/notice-item.vue";
+import { getMsgList } from "@/common/request/apis/index.js";
 export default {
   components: {
     noticeItem,
   },
   data() {
     return {
-      noticeList: [
-        {
-          type: 1,
-          sn: "123654",
-          time: "",
-          isRead: false,
-        },
-        {
-          type: 2,
-          sn: "aa123654",
-          time: "",
-          isRead: true,
-        },
-      ],
+      currentPage: 1,
+      pageSize: 10,
+      loadStatus: "loadmore", //加载前值为loadmore,加载中为loading,没有数据为nomore
+      list: [],
     };
   },
+  onLoad() {
+    this.loadData();
+  },
+  onPullDownRefresh() {
+    // 下拉刷新
+    this.onRefresh();
+  },
+  onReachBottom() {
+    // 触底加载更多
+    this.onLoadMore();
+  },
+  methods: {
+    async onRefresh() {
+      try {
+        await this.loadData(true);
+      } finally {
+        uni.stopPullDownRefresh();
+      }
+    },
+    async onLoadMore() {
+      if (this.loadStatus !== "loadmore") return;
+      this.loadStatus = "loading";
+      try {
+        await this.loadData();
+      } catch (e) {
+        this.loadStatus = "loadmore";
+      }
+    },
+    async loadData(isRefresh = false) {
+      if (isRefresh) {
+        this.currentPage = 1;
+        this.list = [];
+      }
+
+      try {
+        this.loadStatus = "loading";
+        const currentPage = this.currentPage;
+        const pageSize = this.pageSize;
+        const params = {
+          currentPage,
+          pageSize,
+        };
+        console.log("params=====", params);
+        const res = await getMsgList(params);
+        const { rows, total } = res.data;
+        console.log("res====", res);
+        this.list = [...this.list, ...rows];
+        if (currentPage * pageSize < Number(total)) {
+          this.currentPage++;
+          this.loadStatus = "loadmore";
+        } else {
+          this.loadStatus = "nomore";
+        }
+      } catch (error) {}
+    },
+    toDetail(val) {
+      switch (val.type) {
+        case "拣货任务":
+          uni.navigateTo({
+            url: `/pages/picking-task/detail?id=${val.title}`,
+          });
+          break;
+        case "采购入库":
+          uni.navigateTo({
+            url: `/pages/purchase/detail?id=${val.title}`,
+          });
+          break;
+        case "盘点任务":
+          uni.navigateTo({
+            url: `/pages/inventory-task/taskDetail?id=${val.title}`,
+          });
+          break;
+        case "复核任务":
+          if (val.content.includes("CGDD")) {
+            uni.navigateTo({
+              url: `/pages/purchase/detail?id=${val.title}`,
+            });
+          } else {
+            uni.navigateTo({
+              url: `/pages/picking-task/detail?id=${val.title}`,
+            });
+          }
+          break;
+
+        default:
+          break;
+      }
+    },
+  },
 };
 </script>
 
@@ -52,6 +148,9 @@ export default {
   background-color: #f0f6fb;
   .container_main {
     padding: 32rpx 24rpx;
+    .item-wrap {
+      margin-bottom: 24rpx;
+    }
     .time-box {
       position: relative;
       color: #000;

+ 0 - 114
pages/inventory-inquiry/components/good-item.vue

@@ -1,114 +0,0 @@
-<template>
-  <view>
-    <view class="good-item" @click="toDetail">
-      <view class="good-msg">
-        <u-image
-          :src="item.imgNameArr[0] || ''"
-          width="128rpx"
-          height="128rpx"
-        ></u-image>
-        <view class="ss-m-l-16">
-          <view class="good-msg-name">{{ item.materialName }}</view>
-          <view class="good-msg-txm">条形码:{{ item.barCode }}</view>
-        </view>
-      </view>
-      <view class="good-cont">
-        <view class="good-cont-item">
-          <view class="item-label">规格</view>
-          <view class="item-value">{{ item.materialStandard || "-" }}</view>
-        </view>
-        <view class="good-cont-item" @click.stop="calendarClick">
-          <view class="item-label">生产日期</view>
-          <view class="item-value">{{
-            item.productionDate
-              ? $u.timeFormat(item.productionDate, "yyyy-mm-dd")
-              : "-"
-          }}</view>
-        </view>
-        <view class="good-cont-item">
-          <view class="item-label">库存</view>
-          <view class="item-value"
-            >{{ item.inventory ? (item.inventory * 1).toFixed(0) : "0"
-            }}{{ item.commodityUnit || "" }}</view
-          >
-        </view>
-        <view class="good-cont-item">
-          <view class="item-label">库位</view>
-          <view class="item-value">{{ item.position || "-" }}</view>
-        </view>
-      </view>
-      <slot></slot>
-    </view>
-  </view>
-</template>
-
-<script>
-export default {
-  props: {
-    item: {
-      type: Object,
-      default: () => {},
-    },
-  },
-  data() {
-    return {
-      calendarShow: false,
-      value1: Number(new Date()),
-      maxDate: Number(new Date()),
-    };
-  },
-  methods: {
-    toDetail() {
-      this.$emit("toDetail", this.item);
-    },
-    calendarClick() {
-      this.$emit("calendarClick", this.item);
-    },
-  },
-};
-</script>
-
-<style lang="scss" scoped>
-.good-item {
-  padding: 24rpx 0;
-  border-bottom: 4rpx solid #f0f6fb;
-  .good-msg {
-    display: flex;
-    align-items: center;
-    padding: 0 24rpx;
-    &-name {
-      color: #333;
-      font-family: "PingFang SC";
-      font-size: 28rpx;
-      font-weight: 500;
-      margin-bottom: 16rpx;
-    }
-    &-txm {
-      color: #999;
-      font-family: "PingFang SC";
-      font-size: 28rpx;
-      font-weight: 400;
-    }
-  }
-  .good-cont {
-    display: grid;
-    grid-template-columns: 25% 45% 30%;
-    margin-top: 16rpx;
-    padding: 0 24rpx;
-    &-item {
-      font-family: "PingFang SC";
-      font-weight: 400;
-      margin-bottom: 24rpx;
-      .item-label {
-        color: #999;
-        font-size: 24rpx;
-        margin-bottom: 16rpx;
-      }
-      .item-value {
-        color: #000;
-        font-size: 28rpx;
-      }
-    }
-  }
-}
-</style>

+ 42 - 3
pages/inventory-inquiry/index.vue

@@ -77,7 +77,19 @@
               @scrolltolower="onLoadMore"
             >
               <block v-for="(item, i) in goodsList" :key="i">
-                <good-item :item="item"></good-item>
+                <goodCard
+                  :goodImg="
+                    item.imgNameArr && item.imgNameArr[0]
+                      ? item.imgNameArr[0]
+                      : ''
+                  "
+                  :goodName="item.materialName"
+                  :goodDesValue="item.sku"
+                  goodDesTitle="SKU"
+                  :columns="columns"
+                  :item="item"
+                >
+                </goodCard>
               </block>
               <block v-if="goodsList.length == 0">
                 <u-empty
@@ -115,15 +127,17 @@ import {
   inventoryPositionTree,
   materialCategoryTree,
 } from "@/common/request/apis/inventoryInquiry";
-import goodItem from "./components/good-item.vue";
+import goodCard from "@/components/good-card/good-card.vue";
+
 import { mapGetters } from "vuex";
 
 export default {
   components: {
-    goodItem,
+    goodCard,
     leoTree,
   },
   data() {
+    const that = this;
     return {
       offsetTop: 0,
       current: 0,
@@ -162,6 +176,30 @@ export default {
       goodsList: [],
       pageSize: 10,
       currentPage: 1,
+
+      columns: [
+        { title: "规格", key: "materialStandard" },
+        {
+          title: "生产日期",
+          key: "productionDate",
+          formatter: (key, formData) => {
+            return formData.productionDate
+              ? that.$u.timeFormat(formData.productionDate, "yyyy-mm-dd")
+              : "/";
+          },
+        },
+        {
+          title: "库存",
+          key: "inventory",
+          formatter: (key, formData) => {
+            const inventory = formData.inventory
+              ? (formData.inventory * 1).toFixed(0)
+              : "0";
+            return `${inventory}${formData.commodityUnit || ""}`;
+          },
+        },
+        { title: "库位", key: "position" },
+      ],
       queryParams: {
         type: "all",
         categoryId: "",
@@ -382,6 +420,7 @@ export default {
         display: flex;
         .goods-cont-left {
           width: 190rpx;
+          flex: 0 0 190rpx;
           background-color: #f0f6fb;
           .type-item {
             width: 100%;

+ 18 - 11
pages/inventory-task/detail.vue

@@ -17,19 +17,22 @@
 
     <u-sticky bgColor="#F5F6F7" :offsetTop="offsetTop">
       <!-- 基本信息 吸顶 -->
-      <view class="search-box">
-        <u-search
-          placeholder="输入货物名称/库位"
-          shape="square"
-          :showAction="false"
-          @search="onRefresh"
-          @clear="onRefresh"
-          v-model="number"
-        ></u-search>
-        <view class="scan-icon flex_box flex_row_center" @click="scanCode">
-          <image src="@/static/image/scan-icon-2.png" mode=""></image>
+      <view style="background-color: #fff">
+        <view class="search-box">
+          <u-search
+            placeholder="输入货物名称/库位"
+            shape="square"
+            :showAction="false"
+            @search="onRefresh"
+            @clear="onRefresh"
+            v-model="number"
+          ></u-search>
+          <view class="scan-icon flex_box flex_row_center" @click="scanCode">
+            <image src="@/static/image/scan-icon-2.png" mode=""></image>
+          </view>
         </view>
       </view>
+
       <view class="info-card">
         <view class="info-item page-title">
           {{ inventoryInfo.taskName }}
@@ -171,6 +174,7 @@
           <u-tag
             :text="`盘亏${item.inventory - item.newInventory}`"
             bg-color="#FF4E02"
+            borderColor="#FF4E02"
             color="#ffffff"
             class="action-btn"
             v-if="item.status === 3"
@@ -179,6 +183,7 @@
           <u-tag
             :text="`盘盈${item.newInventory - item.inventory}`"
             bg-color="#F59701"
+            borderColor="#F59701"
             color="#ffffff"
             class="action-btn"
             v-if="item.status === 2"
@@ -187,6 +192,7 @@
           <u-tag
             text="无差异"
             bg-color="#00B97B"
+            borderColor="#00B97B"
             color="#ffffff"
             class="action-btn"
             v-if="item.status === 4"
@@ -195,6 +201,7 @@
           <u-tag
             text="未盘"
             bg-color="#0256FF"
+            borderColor="#0256FF"
             color="#ffffff"
             class="action-btn"
             v-if="item.status === 1"

+ 1 - 1
pages/inventory-task/index.vue

@@ -1,7 +1,7 @@
 <template>
   <view class="check-page">
     <u-navbar height="40px" title="盘点" bgColor="#fff" autoBack placeholder>
-      <view class="u-nav-slot depot-label" slot="right" @click="stashClick">
+      <view class="u-nav-slot depot-label" slot="right">
         <view class="name">{{ curDepotName }}</view>
       </view>
     </u-navbar>

+ 1 - 0
pages/login/components/account-login.vue

@@ -78,6 +78,7 @@
 						if (res.data.msgTip === 'user can login') {
 							let userInfo = {
 								token:res.data.token,
+								roleName: res.data.roleName,
 								...res.data.user
 							}
 							this.$store.dispatch('userLogin',userInfo)

+ 0 - 184
pages/picking-task/components/task-item.vue

@@ -1,184 +0,0 @@
-<template>
-  <view class="task-item">
-    <view @click="detailClick">
-      <view class="task-head">
-        <view class="sn-box">单据编号:{{ item.number }}</view>
-        <view v-if="type == 'caigou'">
-          <view class="tips tips-red" v-if="item.status == 1">待入库</view>
-          <view class="tips tips-greed" v-if="item.status == 2">已入库</view>
-          <view class="tips tips-yellow" v-if="item.status == 4">入库中</view>
-        </view>
-        <view v-else>
-          <view class="tips tips-red" v-if="item.status == 1">待拣货</view>
-          <view class="tips tips-greed" v-if="item.status == 2">已拣货</view>
-          <view class="tips tips-yellow" v-if="item.status == 4">拣货中</view>
-        </view>
-      </view>
-      <view class="task-line" v-if="type == 'caigou'">
-        <view>供应商:</view>
-        <view>{{ item.supplierName }}</view>
-      </view>
-      <view class="task-line" v-else>
-        <view>客户名称:</view>
-        <view>{{ item.supplierName }}</view>
-      </view>
-      <view class="task-line">
-        <view>单据日期:</view>
-        <view>{{ item.operTime }}</view>
-      </view>
-      <view class="task-line">
-        <view class="task-line2">
-          <view>货物总数:</view>
-          <view class="task-num">{{ item.goodsQuantity }}件</view>
-        </view>
-        <view class="task-line2">
-          <view>货物种类:</view>
-          <view class="task-num">{{ item.goodsTypeCount || 0 }}种</view>
-        </view>
-      </view>
-    </view>
-    <view class="task-bottom">
-      <view v-if="type == 'caigou'">
-        <view
-          class="btn btn-1"
-          v-if="item.status == 1 || item.status == 4"
-          @click="toStorage"
-          >去入库</view
-        >
-        <view class="btn btn-2" v-else @click="toDetail">详情</view>
-      </view>
-      <view v-else>
-        <view
-          class="btn btn-1"
-          v-if="item.status == 1 || item.status == 4"
-          @click="toStorage"
-          >去出库</view
-        >
-        <view class="btn btn-2" v-else @click="toDetail">详情</view>
-      </view>
-    </view>
-  </view>
-</template>
-
-<script>
-export default {
-  props: {
-    item: {
-      type: Object,
-      default: () => {},
-    },
-    type: {
-      type: String,
-      default: "",
-    },
-  },
-  data() {
-    return {};
-  },
-  methods: {
-    toStorage() {
-      this.$emit("toStorage", this.item);
-    },
-    toDetail() {
-      this.$emit("toDetail", this.item);
-    },
-    detailClick() {
-      if (this.item.status == 1 || this.item.status == 4) {
-        this.toStorage();
-      } else {
-        this.toDetail();
-      }
-    },
-  },
-};
-</script>
-
-<style lang="scss" scoped>
-.task-item {
-  width: 100%;
-  background-color: #fff;
-  border-radius: 16rpx;
-  padding: 24rpx 24rpx 0;
-  margin-bottom: 24rpx;
-  .task-head {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    .sn-box {
-      color: #333;
-      font-family: "PingFang SC";
-      font-size: 28rpx;
-      font-weight: 500;
-    }
-    .tips {
-      font-family: "PingFang SC";
-      font-size: 22rpx;
-      font-weight: 400;
-      width: 120rpx;
-      height: 44rpx;
-      border-radius: 8rpx;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-    }
-    .tips-red {
-      color: #ff3b1d;
-      background: rgba(255, 59, 29, 0.2);
-    }
-    .tips-greed {
-      color: #00b97b;
-      background: rgba(0, 185, 123, 0.2);
-    }
-    .tips-yellow {
-      color: #f57701;
-      background: rgba(245, 151, 1, 0.2);
-    }
-  }
-
-  .task-line {
-    display: flex;
-    align-items: center;
-    color: #666;
-    font-family: "PingFang SC";
-    font-size: 28rpx;
-    font-weight: 400;
-    margin-top: 16rpx;
-  }
-  .task-line2 {
-    width: 50%;
-    display: flex;
-    align-items: center;
-    .task-num {
-      color: #0256ff;
-    }
-  }
-
-  .task-bottom {
-    border-top: 1px solid #f0f0f0;
-    margin-top: 32rpx;
-    height: 104rpx;
-    display: flex;
-    align-items: center;
-    justify-content: flex-end;
-    .btn {
-      width: 144rpx;
-      height: 56rpx;
-      border-radius: 8rpx;
-      font-size: 28rpx;
-      display: flex;
-      align-items: center;
-      justify-content: center;
-      font-family: "PingFang SC";
-    }
-    .btn-1 {
-      background: #0256ff;
-      color: #fff;
-    }
-    .btn-2 {
-      border: 1px solid #0256ff;
-      background: rgba(2, 86, 255, 0.2);
-      color: #0256ff;
-    }
-  }
-}
-</style>

+ 36 - 35
pages/picking-task/delivery.vue

@@ -119,17 +119,10 @@
               <view class="num-box-text">已确认出库数量</view>
               <u-number-box
                 v-model="item.materialNumber"
-                min="0"
+                :min="0"
                 :inputWidth="56"
                 :max="item.inventory"
               >
-                <!-- <view slot="minus" class="minus">
-									<u-icon name="minus" color="#0256FF" size="12"></u-icon>
-								</view>
-								<text slot="input" class="input">{{item.materialNumber}}</text>
-								<view slot="plus" class="plus">
-									<u-icon name="plus" color="#FFFFFF" size="12"></u-icon>
-								</view> -->
               </u-number-box>
             </view>
           </good-item>
@@ -203,9 +196,11 @@ import {
   orderDetail,
   orderInfo,
   orderSubmit,
+  getSkuByUpc,
 } from "@/common/request/apis/purchase";
 import { mapGetters } from "vuex";
 import blePrintMixin from "@/common/mixins/blePrintMixin.js";
+
 export default {
   mixins: [blePrintMixin],
   components: {
@@ -219,7 +214,7 @@ export default {
     return {
       popText: {
         errorText: "实际出库数量与应出库数量有差异,是否确认提交?",
-        successText: "出库成功!",
+        successText: "您的拣货出库任务已提交,审核后方可生效!",
       },
       goodsShow: false,
       scanedShow: false,
@@ -247,7 +242,6 @@ export default {
   },
   onLoad(e) {
     this.id = e.id;
-    this.status = e.status;
     this.getOrderDetail(e.id);
     this.getOrderInfo(e.id);
   },
@@ -262,18 +256,6 @@ export default {
       }
       return num;
     },
-    // 手动输入的数量
-    goodsNum() {
-      let num = 0;
-      if (this.goodsList.length == 0 || !this.goodsList) {
-        num = 0;
-      } else {
-        this.goodsList.forEach((item) => {
-          num += item.materialNumber;
-        });
-      }
-      return num;
-    },
     // 订单返回的数量
     orderGoodsNum() {
       let num = 0;
@@ -288,14 +270,28 @@ export default {
     },
   },
   onShow() {
-    uni.$on("scanFinish", (data) => {
-      if (this.goodsList.length == 0) return uni.$u.toast("该货物不属于该任务");
-      let index = this.goodsList.findIndex((item) => item.barCode == data);
-      if (index == -1) return uni.$u.toast("该货物不属于该任务");
-      this.scanIndex = index;
-      this.scanNum = this.goodsList[index].materialNumber;
-      this.scanMaxNum = this.goodsList[index].inventory;
-      this.scanedShow = true;
+    uni.$on("scanFinish", async (data) => {
+      try {
+        const params = {
+          upc: data,
+        };
+        console.log("params===", params);
+        const res = await getSkuByUpc(params);
+        console.log("getSkuByUpc====", res);
+        if (res.code === 200) {
+          const sku = res.data;
+          if (this.goodsList.length == 0)
+            return uni.$u.toast("该货物不属于该任务");
+          let index = this.goodsList.findIndex((item) => item.sku == sku);
+          if (index == -1) return uni.$u.toast("该货物不属于该任务");
+          this.scanIndex = index;
+          this.scanNum = this.goodsList[index].materialNumber;
+          this.scanMaxNum = this.goodsList[index].inventory;
+          this.scanedShow = true;
+        } else {
+          uni.$u.toast(res.msg);
+        }
+      } catch (error) {}
     });
   },
   onHide() {
@@ -316,9 +312,6 @@ export default {
       });
       this.calendarShow = false;
     },
-    calendarCole() {
-      this.calendarShow = false;
-    },
     calendarClick(item) {
       console.log(item.productionDate, "item.productionDate");
       this.chooseGoodsInfo = item;
@@ -333,6 +326,7 @@ export default {
       orderInfo(id).then((res) => {
         if (res.code == 200) {
           this.orderInfo = res.data;
+          this.status = res.data.status;
           console.log("this.orderInfo====", this.orderInfo);
         }
       });
@@ -372,7 +366,7 @@ export default {
       console.log("this.goodsList=====", this.goodsList);
       let materials = this.goodsList.map((item) => {
         return {
-          barCode: item.barCode,
+          barCode: item.sku,
           materialNumber: item.materialNumber,
           productionDate: item.productionDate
             ? this.$u.timeFormat(item.productionDate, "yyyy-mm-dd")
@@ -384,6 +378,7 @@ export default {
         materials: materials,
         voucherPicture: this.voucherPicture || "",
         remark: this.orderInfo.mark || "",
+        number: this.orderInfo.number,
       };
       console.log("orderSubmit========params====", params);
       orderSubmit(params).then((res) => {
@@ -443,18 +438,24 @@ export default {
 
       .info-line {
         border-bottom: 1px solid #f4f4f4;
-        min-height: 92rpx;
+        padding: 24rpx 0;
         color: #333;
         font-family: "PingFang SC";
         font-size: 28rpx;
+        line-height: 1.5;
         font-weight: 400;
         display: flex;
         align-items: center;
 
         &-label {
+          flex: 0 0 162rpx;
           width: 162rpx;
         }
 
+        &-value {
+          word-break: break-all;
+        }
+
         .must-box {
           color: #ff3b1d;
         }

+ 84 - 31
pages/picking-task/detail.vue

@@ -92,6 +92,30 @@
             {{ orderInfo.submitTime }}
           </view>
         </view>
+        <view class="info-line" v-if="orderInfo.auditorName">
+          <view class="info-line-label">
+            <text>驳回人</text>
+          </view>
+          <view class="info-line-value">
+            {{ orderInfo.auditorName }}
+          </view>
+        </view>
+        <view class="info-line" v-if="orderInfo.rejectTime">
+          <view class="info-line-label">
+            <text>驳回时间</text>
+          </view>
+          <view class="info-line-value">
+            {{ $u.timeFormat(orderInfo.rejectTime, "yyyy-mm-dd hh:MM:ss") }}
+          </view>
+        </view>
+        <view class="info-line" v-if="orderInfo.reject">
+          <view class="info-line-label">
+            <text>驳回原因</text>
+          </view>
+          <view class="info-line-value">
+            {{ orderInfo.reject }}
+          </view>
+        </view>
       </view>
       <view class="btn-box">
         <view class="btn-cont" @click="isUnfold = !isUnfold">
@@ -118,23 +142,20 @@
               <u-number-box
                 v-model="item.actualQuantityInStorage"
                 disabled
-                min="0"
+                :min="0"
                 :inputWidth="56"
                 :max="item.inventory"
               >
-                <!-- <view slot="minus" class="minus">
-									<u-icon name="minus" color="#DADADA" size="12"></u-icon>
-								</view>
-								<text slot="input" class="input">{{(item.actualQuantityInStorage * 1).toFixed(0) || 0}}</text>
-								<view slot="plus" class="plus">
-									<u-icon name="plus" color="#FFFFFF" size="12"></u-icon>
-								</view> -->
               </u-number-box>
             </view>
           </good-item>
         </block>
       </view>
     </view>
+    <view class="footer-box" v-if="auditState == '1'">
+      <u-button class="cancelBtn" @tap="showReject = true">驳回</u-button>
+      <u-button class="submitBtn" @tap="submit('2')">复核通过</u-button>
+    </view>
     <!-- 打印条码弹框 -->
     <print-pop
       :show.sync="blePrintPop.show"
@@ -158,34 +179,38 @@
       :extraText="bleErrorTipPop.extraText"
     >
     </ble-tip-pop>
+    <auditReject :show.sync="showReject" @ok="onReject" />
   </view>
 </template>
 
 <script>
 import goodItem from "@/components/good-item/good-item.vue";
+import auditReject from "@/components/audit-reject/audit-reject.vue";
 import { orderDetail, orderInfo } from "@/common/request/apis/purchase";
 import { mapGetters } from "vuex";
 import blePrintMixin from "@/common/mixins/blePrintMixin.js";
+import { setReviewTask } from "@/common/request/apis/aduit.js";
 
 export default {
   mixins: [blePrintMixin],
   components: {
     goodItem,
+    auditReject,
   },
   data() {
     return {
-      errorShow: false,
-      successShow: false,
       isUnfold: true, //是否展开
       orderInfo: {},
       goodsList: [],
       status: null,
+      auditState: "0",
+      showReject: false,
     };
   },
   onLoad(e) {
-    this.status = e.status;
     this.getOrderInfo(e.id);
     this.getOrderDetail(e.id);
+    this.auditState = e.auditState || "0";
   },
   computed: {
     ...mapGetters(["depotInfo"]),
@@ -195,6 +220,8 @@ export default {
       orderInfo(id).then((res) => {
         if (res.code == 200) {
           this.orderInfo = res.data;
+          this.status = res.data.status;
+          console.log("orderInfo===", res);
         }
       });
     },
@@ -209,25 +236,43 @@ export default {
             }
             item.materialNumber = 0;
           });
+          console.log("goodsList=====", res.data);
           this.goodsList = res.data.rows;
         }
       });
     },
-    submitClick() {},
-    confirm() {
-      this.errorShow = false;
-    },
-    backClick() {},
-    // 扫码确认
-    scanConfirm() {},
-    manualClick() {
-      this.goodsShow = true;
-    },
     toDetail(val) {
       uni.navigateTo({
         url: `/pages/goods/detail?id=${val.id}&name=${val.materialName}&materialId=${val.materialId}`,
       });
     },
+    onReject(reject) {
+      this.submit("7", reject);
+    },
+    async submit(status, reject) {
+      try {
+        const params = {
+          id: this.orderInfo.id,
+          status,
+          number: this.orderInfo.number,
+        };
+        if (reject) {
+          params.reject = reject;
+        }
+        const result = await setReviewTask(params);
+        console.log("setReviewTask====params", params);
+        console.log("setReviewTask====result", result);
+        if (result.code === 200) {
+          uni.$u.toast(result.msg);
+          setTimeout(() => {
+            uni.navigateBack();
+          }, 1000);
+          uni.setStorageSync("auditTaskRefresh", true);
+        } else {
+          uni.$u.toast(result.msg);
+        }
+      } catch (error) {}
+    },
   },
 };
 </script>
@@ -248,18 +293,24 @@ export default {
 
       .info-line {
         border-bottom: 1px solid #f4f4f4;
-        min-height: 92rpx;
+        padding: 24rpx 0;
         color: #333;
         font-family: "PingFang SC";
         font-size: 28rpx;
+        line-height: 1.5;
         font-weight: 400;
         display: flex;
         align-items: center;
 
         &-label {
+          flex: 0 0 162rpx;
           width: 162rpx;
         }
 
+        &-value {
+          word-break: break-all;
+        }
+
         .must-box {
           color: #ff3b1d;
         }
@@ -378,23 +429,25 @@ export default {
     right: 0;
     display: flex;
     align-items: center;
-    justify-content: space-between;
-    padding: 0 40rpx 0 60rpx;
-    .footer-box-l {
+    justify-content: center;
+    .cancelBtn {
+      width: 244rpx;
+      height: 80rpx;
+      border-radius: 16rpx;
       color: #666;
       font-family: "PingFang SC";
-      font-size: 28rpx;
-      font-weight: 400;
+      font-size: 32rpx;
+      font-weight: 500;
+      margin-right: 20rpx;
     }
     .submitBtn {
-      width: 362rpx;
-      height: 76rpx;
+      width: 244rpx;
+      height: 80rpx;
       border-radius: 16rpx;
       background: #0256ff;
       color: #fff;
-      font-size: 28rpx;
+      font-size: 32rpx;
       font-weight: 500;
-      margin: 0;
     }
   }
 }

+ 183 - 22
pages/picking-task/index.vue

@@ -43,12 +43,83 @@
       </u-sticky>
       <view class="task-cont">
         <block v-for="(item, i) in taskList" :key="i">
-          <task-item
-            :item="item"
-            @toStorage="toStorage"
-            @toDetail="toDetail"
+          <task-card
             :key="`${item.id}-${item.status}`"
-          ></task-item>
+            :columns="taskColumns"
+            :formData="item"
+            @handleClickField="handleClickField"
+          >
+            <!-- 状态 -->
+            <view slot="rightTop">
+              <u-tag
+                v-if="item.status == 1"
+                text="待拣货"
+                plain
+                borderColor="rgba(255, 59, 29, 0.2)"
+                color="#ff3b1d"
+                bgColor="rgba(255, 59, 29, 0.2)"
+              ></u-tag>
+              <u-tag
+                v-if="item.status == 6"
+                text="待复核"
+                plain
+                borderColor="rgba(255, 59, 29, 0.2)"
+                color="#ff3b1d"
+                bgColor="rgba(255, 59, 29, 0.2)"
+              ></u-tag>
+              <u-tag
+                v-if="item.status == 7"
+                text="复核驳回"
+                plain
+                borderColor="rgba(255, 59, 29, 0.2)"
+                color="#ff3b1d"
+                bgColor="rgba(255, 59, 29, 0.2)"
+              ></u-tag>
+              <u-tag
+                v-if="item.status == 3"
+                text="部分拣货"
+                plain
+                borderColor="rgba(0, 185, 123, 0.2)"
+                color="#00b97b"
+                bgColor="rgba(0, 185, 123, 0.2)"
+              ></u-tag>
+              <u-tag
+                v-if="item.status == 2"
+                text="已拣货"
+                plain
+                borderColor="rgba(0, 185, 123, 0.2)"
+                color="#00b97b"
+                bgColor="rgba(0, 185, 123, 0.2)"
+              ></u-tag>
+              <u-tag
+                v-if="item.status == 4"
+                text="拣货中"
+                plain
+                borderColor="rgba(245, 151, 1, 0.2)"
+                color="#f57701"
+                bgColor="rgba(245, 151, 1, 0.2)"
+              ></u-tag>
+            </view>
+            <!-- 操作栏 -->
+            <view slot="action" class="action-box">
+              <view class="action-left-box" v-if="item.status == 7"
+                >驳回原因:{{ item.reject }}</view
+              >
+              <view class="task-bottom">
+                <view
+                  class="btn btn-1"
+                  @click="toStorage(item)"
+                  v-if="
+                    item.status == 1 || item.status == 4 || item.status == 7
+                  "
+                  >{{ item.status == 7 ? "重新出库" : "去出库" }}</view
+                >
+                <view class="btn btn-2" @click="toDetail(item)" v-else
+                  >详情</view
+                >
+              </view>
+            </view>
+          </task-card>
         </block>
         <u-loadmore v-if="taskList.length > 0" :status="status" />
         <u-empty
@@ -81,14 +152,14 @@
 </template>
 
 <script>
-import taskItem from "./components/task-item.vue";
+import taskCard from "@/components/task-card/task-card.vue";
 import { saleOrder } from "@/common/request/apis/picking";
 import { orderStartHandle } from "@/common/request/apis/purchase";
 import { mapGetters } from "vuex";
 
 export default {
   components: {
-    taskItem,
+    taskCard,
   },
   data() {
     return {
@@ -108,10 +179,22 @@ export default {
             id: "1",
           },
           {
+            label: "待复核",
+            id: "6",
+          },
+          {
+            label: "复核驳回",
+            id: "7",
+          },
+          {
             label: "拣货中",
             id: "4",
           },
           {
+            label: "部分拣货",
+            id: "3",
+          },
+          {
             label: "已拣货",
             id: "2",
           },
@@ -134,6 +217,46 @@ export default {
           "十二月",
         ],
       ],
+      taskColumns: [
+        {
+          title: "单据编号",
+          key: "number",
+          titleStyle: {
+            color: "#333",
+            fontSize: "28rpx",
+            fontWeight: 500,
+          },
+          valueStyle: {
+            color: "#333",
+            fontSize: "28rpx",
+            fontWeight: 500,
+          },
+        },
+        {
+          title: "客户名称",
+          key: "supplierName",
+        },
+        {
+          title: "单据日期",
+          key: "operTime",
+        },
+        {
+          title: "货物总数",
+          key: "goodsQuantity",
+          span: 12,
+          valueStyle: {
+            color: "#0256ff",
+          },
+        },
+        {
+          title: "货物种类",
+          key: "goodsTypeCount",
+          span: 12,
+          valueStyle: {
+            color: "#0256ff",
+          },
+        },
+      ],
       defaultIndex2: [],
       defaultIndex3: [],
       taskList: [],
@@ -258,33 +381,26 @@ export default {
         this.params.endTime = "";
       }
     },
-    // 获取picker默认index
-    getDefaultIndex(val, list) {
-      let arr = [];
-      let index = list[0].findIndex((item) => item.label == val);
-      arr = [index];
-      return arr;
-    },
-    // 点击操作
-    toOrderStartHandle(id) {
-      orderStartHandle(id).then((res) => {
+    // 出库
+    toStorage(val) {
+      uni.setStorageSync("orderRefresh", true);
+      orderStartHandle(val.id).then((res) => {
         if (res.code == 200) {
           uni.navigateTo({
-            url: `/pages/picking-task/delivery?id=${id}`,
+            url: `/pages/picking-task/delivery?id=${val.id}`,
           });
         }
       });
     },
-    // 出库
-    toStorage(val) {
-      this.toOrderStartHandle(val.id);
-    },
     toDetail(val) {
       console.log(val, "val");
       uni.navigateTo({
         url: `/pages/picking-task/detail?id=${val.id}`,
       });
     },
+    handleClickField(key, itemData) {
+      this.toDetail(itemData);
+    },
   },
 };
 </script>
@@ -343,4 +459,49 @@ export default {
     }
   }
 }
+.action-box {
+  padding-bottom: 24rpx;
+  height: 80rpx;
+  box-sizing: border-box;
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
+  width: 100%;
+}
+
+.action-left-box {
+  color: #ff3b1d;
+  font-family: "PingFang SC";
+  font-size: 28rpx;
+  font-weight: 400;
+  width: 400rpx;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.task-bottom {
+  flex: 1;
+  display: inline-flex;
+  align-items: center;
+  justify-content: flex-end;
+  .btn {
+    width: 144rpx;
+    height: 56rpx;
+    border-radius: 8rpx;
+    font-size: 28rpx;
+    line-height: 56rpx;
+    text-align: center;
+    margin-left: 12rpx;
+    font-family: "PingFang SC";
+  }
+  .btn-1 {
+    background: #0256ff;
+    color: #fff;
+  }
+  .btn-2 {
+    border: 1px solid #0256ff;
+    background: rgba(2, 86, 255, 0.2);
+    color: #0256ff;
+  }
+}
 </style>

+ 85 - 31
pages/purchase/detail.vue

@@ -100,6 +100,30 @@
             {{ orderInfo.operTime }}
           </view>
         </view>
+        <view class="info-line" v-if="orderInfo.auditorName">
+          <view class="info-line-label">
+            <text>{{orderInfo.status=='7'?'驳回人':'复核人'}}</text>
+          </view>
+          <view class="info-line-value">
+            {{ orderInfo.auditorName }}
+          </view>
+        </view>
+        <view class="info-line" v-if="orderInfo.rejectTime">
+          <view class="info-line-label">
+            <text>{{orderInfo.status=='7'?'驳回时间':'复核时间'}}</text>
+          </view>
+          <view class="info-line-value">
+            {{ $u.timeFormat(orderInfo.rejectTime, "yyyy-mm-dd hh:MM:ss") }}
+          </view>
+        </view>
+        <view class="info-line" v-if="orderInfo.reject">
+          <view class="info-line-label">
+            <text>驳回原因</text>
+          </view>
+          <view class="info-line-value">
+            {{ orderInfo.reject }}
+          </view>
+        </view>
       </view>
       <view class="btn-box">
         <view class="btn-cont" @click="isUnfold = !isUnfold">
@@ -125,22 +149,20 @@
               <view class="num-box-text">已确认入库数量</view>
               <u-number-box
                 v-model="item.actualQuantityInStorage"
+                :min="0"
                 disabled
                 :inputWidth="56"
               >
-                <!-- <view slot="minus" class="minus">
-									<u-icon name="minus" color="#DADADA" size="12"></u-icon>
-								</view>
-								<text slot="input" class="input">{{item.actualQuantityInStorage ? (item.actualQuantityInStorage*1).toFixed(0) : 0}}</text>
-								<view slot="plus" class="plus">
-									<u-icon name="plus" color="#FFFFFF" size="12"></u-icon>
-								</view> -->
               </u-number-box>
             </view>
           </good-item>
         </block>
       </view>
     </view>
+    <view class="footer-box" v-if="auditState == '1'">
+      <u-button class="cancelBtn" @tap="showReject = true">驳回</u-button>
+      <u-button class="submitBtn" @tap="submit('2')">复核通过</u-button>
+    </view>
     <!-- 打印条码弹框 -->
     <print-pop
       :show.sync="blePrintPop.show"
@@ -164,34 +186,38 @@
       :extraText="bleErrorTipPop.extraText"
     >
     </ble-tip-pop>
+    <auditReject :show.sync="showReject" @ok="onReject" />
   </view>
 </template>
 
 <script>
 import goodItem from "@/components/good-item/good-item.vue";
+import auditReject from "@/components/audit-reject/audit-reject.vue";
 import { orderDetail, orderInfo } from "@/common/request/apis/purchase";
 import { mapGetters } from "vuex";
 import blePrintMixin from "@/common/mixins/blePrintMixin.js";
+import { setReviewTask } from "@/common/request/apis/aduit.js";
+
 export default {
   mixins: [blePrintMixin],
   components: {
     goodItem,
+    auditReject,
   },
   data() {
     return {
-      errorShow: false,
-      successShow: false,
-      value: 0,
       isUnfold: true, //是否展开
       orderInfo: {},
       goodsList: [],
       status: null,
+      auditState: "0",
+      showReject: false,
     };
   },
   onLoad(e) {
-    this.status = e.status;
     this.getOrderInfo(e.id);
     this.getOrderDetail(e.id);
+    this.auditState = e.auditState || "0";
   },
   computed: {
     ...mapGetters(["depotInfo"]),
@@ -201,6 +227,9 @@ export default {
       orderInfo(id).then((res) => {
         if (res.code == 200) {
           this.orderInfo = res.data;
+          this.status = res.data.status;
+          console.log("this.status=====", this.status);
+          console.log("orderInfo=====", res);
         }
       });
     },
@@ -219,21 +248,38 @@ export default {
         }
       });
     },
-    submitClick() {},
-    confirm() {
-      this.errorShow = false;
-    },
-    backClick() {},
-    // 扫码确认
-    scanConfirm() {},
-    manualClick() {
-      this.goodsShow = true;
-    },
     toDetail(val) {
       uni.navigateTo({
         url: `/pages/goods/detail?id=${val.id}&name=${val.materialName}&materialId=${val.materialId}`,
       });
     },
+    onReject(reject) {
+      this.submit("7", reject);
+    },
+    async submit(status, reject) {
+      try {
+        const params = {
+          id: this.orderInfo.id,
+          status,
+          number: this.orderInfo.number,
+        };
+        if (reject) {
+          params.reject = reject;
+        }
+        const result = await setReviewTask(params);
+        console.log("setReviewTask====params", params);
+        console.log("setReviewTask====result", result);
+        if (result.code === 200) {
+          uni.$u.toast(result.msg);
+          setTimeout(() => {
+            uni.navigateBack();
+          }, 1000);
+          uni.setStorageSync("auditTaskRefresh", true);
+        } else {
+          uni.$u.toast(result.msg);
+        }
+      } catch (error) {}
+    },
   },
 };
 </script>
@@ -254,18 +300,24 @@ export default {
 
       .info-line {
         border-bottom: 1px solid #f4f4f4;
-        min-height: 92rpx;
+        padding: 24rpx 0;
         color: #333;
         font-family: "PingFang SC";
         font-size: 28rpx;
+        line-height: 1.5;
         font-weight: 400;
         display: flex;
         align-items: center;
 
         &-label {
+          flex: 0 0 162rpx;
           width: 162rpx;
         }
 
+        &-value {
+          word-break: break-all;
+        }
+
         .must-box {
           color: #ff3b1d;
         }
@@ -384,23 +436,25 @@ export default {
     right: 0;
     display: flex;
     align-items: center;
-    justify-content: space-between;
-    padding: 0 40rpx 0 60rpx;
-    .footer-box-l {
+    justify-content: center;
+    .cancelBtn {
+      width: 244rpx;
+      height: 80rpx;
+      border-radius: 16rpx;
       color: #666;
       font-family: "PingFang SC";
-      font-size: 28rpx;
-      font-weight: 400;
+      font-size: 32rpx;
+      font-weight: 500;
+      margin-right: 20rpx;
     }
     .submitBtn {
-      width: 362rpx;
-      height: 76rpx;
+      width: 244rpx;
+      height: 80rpx;
       border-radius: 16rpx;
       background: #0256ff;
       color: #fff;
-      font-size: 28rpx;
+      font-size: 32rpx;
       font-weight: 500;
-      margin: 0;
     }
   }
 }

+ 188 - 20
pages/purchase/index.vue

@@ -43,12 +43,83 @@
       </u-sticky>
       <view class="task-cont">
         <block v-for="(item, i) in taskList" :key="`${item.id}-${item.status}`">
-          <task-item
-            :item="item"
-            @toStorage="toStorage"
-            @toDetail="toDetail"
-            type="caigou"
-          ></task-item>
+          <task-card
+            :key="`${item.id}-${item.status}`"
+            :columns="taskColumns"
+            :formData="item"
+            @handleClickField="handleClickField"
+          >
+            <!-- 状态 -->
+            <view slot="rightTop">
+              <u-tag
+                v-if="item.status == 1"
+                text="待入库"
+                plain
+                borderColor="rgba(255, 59, 29, 0.2)"
+                color="#ff3b1d"
+                bgColor="rgba(255, 59, 29, 0.2)"
+              ></u-tag>
+              <u-tag
+                v-if="item.status == 6"
+                text="待复核"
+                plain
+                borderColor="rgba(255, 59, 29, 0.2)"
+                color="#ff3b1d"
+                bgColor="rgba(255, 59, 29, 0.2)"
+              ></u-tag>
+              <u-tag
+                v-if="item.status == 7"
+                text="复核驳回"
+                plain
+                borderColor="rgba(255, 59, 29, 0.2)"
+                color="#ff3b1d"
+                bgColor="rgba(255, 59, 29, 0.2)"
+              ></u-tag>
+              <u-tag
+                v-if="item.status == 3"
+                text="部分入库"
+                plain
+                borderColor="rgba(0, 185, 123, 0.2)"
+                color="#00b97b"
+                bgColor="rgba(0, 185, 123, 0.2)"
+              ></u-tag>
+              <u-tag
+                v-if="item.status == 2"
+                text="已入库"
+                plain
+                borderColor="rgba(0, 185, 123, 0.2)"
+                color="#00b97b"
+                bgColor="rgba(0, 185, 123, 0.2)"
+              ></u-tag>
+              <u-tag
+                v-if="item.status == 4"
+                text="入库中"
+                plain
+                borderColor="rgba(245, 151, 1, 0.2)"
+                color="#f57701"
+                bgColor="rgba(245, 151, 1, 0.2)"
+              ></u-tag>
+            </view>
+            <!-- 操作栏 -->
+            <view slot="action" class="action-box">
+              <view class="action-left-box" v-if="item.status == 7"
+                >驳回原因:{{ item.reject }}</view
+              >
+              <view class="task-bottom">
+                <view
+                  class="btn btn-1"
+                  @click="toStorage(item)"
+                  v-if="
+                    item.status == 1 || item.status == 4 || item.status == 7
+                  "
+                  >{{ item.status == 7 ? "重新入库" : "去入库" }}</view
+                >
+                <view class="btn btn-2" @click="toDetail(item)" v-else
+                  >详情</view
+                >
+              </view>
+            </view>
+          </task-card>
         </block>
         <u-loadmore v-if="taskList.length > 0" :status="status" />
         <u-empty
@@ -81,7 +152,7 @@
 </template>
 
 <script>
-import taskItem from "@/components/task-item/task-item.vue";
+import taskCard from "@/components/task-card/task-card.vue";
 import {
   purchaseInventory,
   orderStartHandle,
@@ -90,7 +161,7 @@ import { mapGetters } from "vuex";
 
 export default {
   components: {
-    taskItem,
+    taskCard,
   },
   data() {
     return {
@@ -110,10 +181,22 @@ export default {
             id: "1",
           },
           {
+            label: "待复核",
+            id: "6",
+          },
+          {
+            label: "复核驳回",
+            id: "7",
+          },
+          {
             label: "入库中",
             id: "4",
           },
           {
+            label: "部分入库",
+            id: "3",
+          },
+          {
             label: "已入库",
             id: "2",
           },
@@ -136,6 +219,46 @@ export default {
           "十二月",
         ],
       ],
+      taskColumns: [
+        {
+          title: "单据编号",
+          key: "number",
+          titleStyle: {
+            color: "#333",
+            fontSize: "28rpx",
+            fontWeight: 500,
+          },
+          valueStyle: {
+            color: "#333",
+            fontSize: "28rpx",
+            fontWeight: 500,
+          },
+        },
+        {
+          title: "供应商",
+          key: "supplierName",
+        },
+        {
+          title: "单据日期",
+          key: "createTime",
+        },
+        {
+          title: "货物总数",
+          key: "goodsQuantity",
+          span: 12,
+          valueStyle: {
+            color: "#0256ff",
+          },
+        },
+        {
+          title: "货物种类",
+          key: "goodsTypeCount",
+          span: 12,
+          valueStyle: {
+            color: "#0256ff",
+          },
+        },
+      ],
       defaultIndex2: [],
       defaultIndex3: [],
       taskList: [],
@@ -201,16 +324,6 @@ export default {
     searchClick() {
       this.init();
     },
-    // 点击操作
-    toOrderStartHandle(id, status) {
-      orderStartHandle(id).then((res) => {
-        if (res.code == 200) {
-          uni.navigateTo({
-            url: `/pages/purchase/put-storage?id=${id}&status=${status}`,
-          });
-        }
-      });
-    },
     tabClick(type) {
       switch (type) {
         case 1:
@@ -273,13 +386,23 @@ export default {
     },
     // 入库
     toStorage(val) {
-      this.toOrderStartHandle(val.id, val.status);
+      uni.setStorageSync("orderRefresh", true);
+      orderStartHandle(val.id).then((res) => {
+        if (res.code == 200) {
+          uni.navigateTo({
+            url: `/pages/purchase/put-storage?id=${val.id}`,
+          });
+        }
+      });
     },
     toDetail(val) {
       uni.navigateTo({
-        url: `/pages/purchase/detail?id=${val.id}&status=${val.status}`,
+        url: `/pages/purchase/detail?id=${val.id}`,
       });
     },
+    handleClickField(key, itemData) {
+      this.toDetail(itemData);
+    },
   },
 };
 </script>
@@ -338,4 +461,49 @@ export default {
     }
   }
 }
+.action-box {
+  padding-bottom: 24rpx;
+  height: 80rpx;
+  box-sizing: border-box;
+  display: flex;
+  align-items: center;
+  justify-content: flex-end;
+  width: 100%;
+}
+
+.action-left-box {
+  color: #ff3b1d;
+  font-family: "PingFang SC";
+  font-size: 28rpx;
+  font-weight: 400;
+  width: 400rpx;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.task-bottom {
+  flex: 1;
+  display: inline-flex;
+  align-items: center;
+  justify-content: flex-end;
+  .btn {
+    width: 144rpx;
+    height: 56rpx;
+    border-radius: 8rpx;
+    font-size: 28rpx;
+    line-height: 56rpx;
+    text-align: center;
+    margin-left: 12rpx;
+    font-family: "PingFang SC";
+  }
+  .btn-1 {
+    background: #0256ff;
+    color: #fff;
+  }
+  .btn-2 {
+    border: 1px solid #0256ff;
+    background: rgba(2, 86, 255, 0.2);
+    color: #0256ff;
+  }
+}
 </style>

+ 37 - 27
pages/purchase/put-storage.vue

@@ -109,7 +109,7 @@
               <view class="num-box-text">已确认入库数量</view>
               <u-number-box
                 v-model="item.materialNumber"
-                min="0"
+                :min="0"
                 :inputWidth="56"
               >
               </u-number-box>
@@ -205,6 +205,7 @@ import {
   orderDetail,
   orderInfo,
   orderSubmit,
+  getSkuByUpc,
 } from "@/common/request/apis/purchase";
 import { mapGetters } from "vuex";
 import blePrintMixin from "@/common/mixins/blePrintMixin.js";
@@ -222,7 +223,7 @@ export default {
     return {
       popText: {
         errorText: "实际入库数量与应入库数量有差异,是否确认提交?",
-        successText: "入库成功!",
+        successText: "您的采购入库任务已提交,审核后方可生效!",
       },
       goodsShow: false,
       scanedShow: false,
@@ -254,18 +255,31 @@ export default {
   },
   onLoad(e) {
     this.id = e.id;
-    this.status = e.status;
     this.getOrderDetail(e.id);
     this.getOrderInfo(e.id);
   },
   onShow() {
-    uni.$on("scanFinish", (data) => {
-      if (this.goodsList.length == 0) return uni.$u.toast("该货物不属于该任务");
-      let index = this.goodsList.findIndex((item) => item.barCode == data);
-      if (index == -1) return uni.$u.toast("该货物不属于该任务");
-      this.scanIndex = index;
-      this.scanNum = this.goodsList[index].materialNumber;
-      this.scanedShow = true;
+    uni.$on("scanFinish", async (data) => {
+      try {
+        const params = {
+          upc: data,
+        };
+        console.log("params===", params);
+        const res = await getSkuByUpc(params);
+        console.log("getSkuByUpc====", res);
+        if (res.code === 200) {
+          const sku = res.data;
+          if (this.goodsList.length == 0)
+            return uni.$u.toast("该货物不属于该任务");
+          let index = this.goodsList.findIndex((item) => item.sku == sku);
+          if (index == -1) return uni.$u.toast("该货物不属于该任务");
+          this.scanIndex = index;
+          this.scanNum = this.goodsList[index].materialNumber;
+          this.scanedShow = true;
+        } else {
+          uni.$u.toast(res.msg);
+        }
+      } catch (error) {}
     });
   },
   onHide() {
@@ -291,18 +305,6 @@ export default {
       }
       return num;
     },
-    // 手动输入的数量
-    goodsNum() {
-      let num = 0;
-      if (this.goodsList.length == 0 || !this.goodsList) {
-        num = 0;
-      } else {
-        this.goodsList.forEach((item) => {
-          num += item.materialNumber;
-        });
-      }
-      return num;
-    },
     // 订单返回的数量
     orderGoodsNum() {
       let num = 0;
@@ -328,9 +330,6 @@ export default {
       });
       this.calendarShow = false;
     },
-    calendarCole() {
-      this.calendarShow = false;
-    },
     calendarClick(item) {
       this.chooseGoodsInfo = item;
       if (item.productionDate) {
@@ -344,6 +343,8 @@ export default {
       orderInfo(id).then((res) => {
         if (res.code == 200) {
           this.orderInfo = res.data;
+          this.status = res.data.status;
+          console.log("this.orderInfo====", this.orderInfo);
         }
       });
     },
@@ -358,6 +359,8 @@ export default {
               item.imgNameArr = [];
             }
           });
+          console.log("2333333333");
+          console.log("res.data====", res.data);
           this.goodsList = res.data.rows;
         }
       });
@@ -377,7 +380,7 @@ export default {
     toOrderSubmit() {
       let materials = this.goodsList.map((item) => {
         return {
-          barCode: item.barCode,
+          barCode: item.sku,
           materialNumber: item.materialNumber,
           productionDate: item.productionDate
             ? this.$u.timeFormat(item.productionDate, "yyyy-mm-dd")
@@ -390,6 +393,7 @@ export default {
         materials: materials,
         voucherPicture: this.voucherPicture || "",
         remark: this.orderInfo.mark || "",
+        number: this.orderInfo.number,
       };
       console.log("params", params);
       orderSubmit(params).then((res) => {
@@ -459,18 +463,24 @@ export default {
 
       .info-line {
         border-bottom: 1px solid #f4f4f4;
-        min-height: 92rpx;
+        padding: 24rpx 0;
         color: #333;
         font-family: "PingFang SC";
         font-size: 28rpx;
+        line-height: 1.5;
         font-weight: 400;
         display: flex;
         align-items: center;
 
         &-label {
+          flex: 0 0 162rpx;
           width: 162rpx;
         }
 
+        &-value {
+          word-break: break-all;
+        }
+
         .must-box {
           color: #ff3b1d;
         }