浏览代码

鼓浪屿药柜增加追溯码特殊处理

hd 4 天之前
父节点
当前提交
0db0a3257c

+ 161 - 144
mini-pro-web/src/components/ProductItem/index.vue

@ -1,159 +1,176 @@
<template>
    <div @click="toSet" class='components-product-item' 
        :class="{'pitem-full':data.cargoCapacity==data.qty, 'pitem-close': data.cargoState!=1, 'pitem-fault': data.faultState==1, 'pitem-active': isActive, 'pitem-main': data.state==21}">
        <div :style="'height: '+ (rate) +'%'" class="pitem-bg"></div>
        <div class="pitem-inner" >
            <div class="kitbox " >
                <div class="box-flex-1">{{wayerNo}}号位</div>
                <div>{{data.qty}}/{{data.cargoCapacity}}</div>
            </div>
            <template v-if="data.shelfStatus==1">
                <div class="ellipsis tc pt12">{{data.drugName}}</div>
                <div class="ellipsis tc pt10">{{data.specif}}</div>
            </template>
            <div v-else class="ellipsis tc pt12 ">未设药品</div>
        </div>
        <div class="tag" v-if="data.state==21">主</div>
        <div class="tag" v-else-if="data.state==20">副</div>
        <img class="gouxuan" src="@/assets/images/gouxuan.png" alt="">
  <div
    @click="toSet"
    class="components-product-item"
    :class="{
      'pitem-full': data.cargoCapacity == data.qty,
      'pitem-close': data.cargoState != 1,
      'pitem-fault': data.faultState == 1,
      'pitem-active': isActive,
      'pitem-main': data.state == 21
    }"
  >
    <div :style="'height: ' + rate + '%'" class="pitem-bg"></div>
    <div class="pitem-inner">
      <div class="kitbox ">
        <div class="box-flex-1">{{ wayerNo }}号位</div>
        <div>{{ data.qty }}/{{ data.cargoCapacity }}</div>
      </div>
      <template v-if="data.shelfStatus == 1">
        <div class="ellipsis tc pt12">{{ data.drugName }}</div>
        <div class="ellipsis tc pt10">{{ data.specif }}</div>
      </template>
      <div v-else class="ellipsis tc pt12 ">未设药品</div>
    </div>
    <div class="tag" v-if="data.state == 21">主</div>
    <div class="tag" v-else-if="data.state == 20">副</div>
    <img class="gouxuan" src="@/assets/images/gouxuan.png" alt="" />
  </div>
</template>
<script>
export default{
    props: ['data', 'index', 'bussuness', 'isView'],//bussuness quick快速补货  isView
    data(){
        return {
            isActive: false
        }
    },
    computed:{
        wayerNo(){
            if(this.data.state==21){
                var arr = this.data.merge.split(",")
                return arr[0] + '~' + arr[arr.length-1]
            }
            return this.data.wayerNo
        },
        rate(){
            var {data} = this
            return (data.qty||0) / (data.cargoCapacity||5) * 100
        },
    },
    watch: {
        'data.isActive':{
            handler(n){
                this.isActive = n
            },
            deep: true
        }
    },
    created() {
        this.isActive = this.data.isActive
    },
    methods:{
        toSet(){
            if(this.isView){
                return
            }
            if(this.bussuness == 'quick'){
                this.isActive = !this.isActive
                this.$emit('onChange', this.isActive)
                return
            }
            if(this.data.state==20){
                this.$toast('不能操作副通道,如要修改请修改它的主通道')
                return
            }
            if(this.data.shelfStatus != 1){
                this.gotoUrl('/drugList', {
                    trackId: this.data.id,
                    deviceId: this.data.idDevice,
                    cargoCapacity: this.data.cargoCapacity
                })
            } else {
                this.gotoUrl('./productDetail', {
                    id: this.data.id,
                })
            }
        }
    },
}
</script>
<style lang='scss' scoped>
.components-product-item{
    overflow: hidden;
    width: 100px;
    height: 80px;
    background: rgb(238, 238, 238);
    border-radius: 10px;
    margin-left: 10px;
    padding: 5px;
    font-size: 14px;
    position: relative;
    &.pitem-full{
        color: #fff;
export default {
  props: ['data', 'index', 'bussuness', 'isView', 'old'], //bussuness quick快速补货  isView
  data() {
    return {
      isActive: false
    }
    &:first-child{
        margin-left: 0;
  },
  computed: {
    wayerNo() {
      if (this.data.state == 21) {
        var arr = this.data.merge.split(',')
        return arr[0] + '~' + arr[arr.length - 1]
      }
      return this.data.wayerNo
    },
    rate() {
      var { data } = this
      return ((data.qty || 0) / (data.cargoCapacity || 5)) * 100
    }
    .pitem-inner{
        position: relative;
        z-index: 1;
        background: transparent;
        line-height: 1.2;
  },
  watch: {
    'data.isActive': {
      handler(n) {
        this.isActive = n
      },
      deep: true
    }
    .pitem-bg{
        background: #17b3ec;
        position: absolute;
        z-index: 0;
        width: 100%;
        bottom: 0;
        left: 0;
        border-bottom-left-radius: 10px;
        border-bottom-right-radius: 10px;
        &.orange{
            background: #ff9526;
        }
        &.red{
                background: #ff5e6c;
  },
  created() {
    this.isActive = this.data.isActive
  },
  methods: {
    toSet() {
      if (this.isView) {
        return
      }
      if (this.bussuness == 'quick') {
        this.isActive = !this.isActive
        this.$emit('onChange', this.isActive)
        return
      }
      if (this.data.state == 20) {
        this.$toast('不能操作副通道,如要修改请修改它的主通道')
        return
      }
      if (this.data.shelfStatus != 1) {
        if (this.old) {
          this.gotoUrl('/oldDrugList', {
            trackId: this.data.id,
            deviceId: this.data.idDevice,
            cargoCapacity: this.data.cargoCapacity
          })
        } else {
          this.gotoUrl('/drugList', {
            trackId: this.data.id,
            deviceId: this.data.idDevice,
            cargoCapacity: this.data.cargoCapacity
          })
        }
      } else {
        this.gotoUrl('./productDetail', {
          id: this.data.id
        })
      }
    }
    .tag{
        color: red;
        position: absolute;
        right: 2px;
        bottom: 2px;
        font-size: 12px;
    }
    &.pitem-close{
        background-color: #ff9526;
        color: #fff;
        .pitem-bg{
            display: none;
        }
  }
}
</script>
<style lang="scss" scoped>
.components-product-item {
  overflow: hidden;
  width: 100px;
  height: 80px;
  background: rgb(238, 238, 238);
  border-radius: 10px;
  margin-left: 10px;
  padding: 5px;
  font-size: 14px;
  position: relative;
  &.pitem-full {
    color: #fff;
  }
  &:first-child {
    margin-left: 0;
  }
  .pitem-inner {
    position: relative;
    z-index: 1;
    background: transparent;
    line-height: 1.2;
  }
  .pitem-bg {
    background: #17b3ec;
    position: absolute;
    z-index: 0;
    width: 100%;
    bottom: 0;
    left: 0;
    border-bottom-left-radius: 10px;
    border-bottom-right-radius: 10px;
    &.orange {
      background: #ff9526;
    }
    &.pitem-fault{
        background-color: #ff5e6c;
        color: #fff;
        .pitem-bg{
            display: none;
        }
    &.red {
      background: #ff5e6c;
    }
    .gouxuan{
        position: absolute;
        right: 0;
        bottom: 0;
        width: 20px;
        display: none;
  }
  .tag {
    color: red;
    position: absolute;
    right: 2px;
    bottom: 2px;
    font-size: 12px;
  }
  &.pitem-close {
    background-color: #ff9526;
    color: #fff;
    .pitem-bg {
      display: none;
    }
    &.pitem-active{
        border: 1px solid red;
        .gouxuan{
            display: block;
        }
  }
  &.pitem-fault {
    background-color: #ff5e6c;
    color: #fff;
    .pitem-bg {
      display: none;
    }
    &.pitem-main{
        width: 280px!important;
  }
  .gouxuan {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 20px;
    display: none;
  }
  &.pitem-active {
    border: 1px solid red;
    .gouxuan {
      display: block;
    }
  }
  &.pitem-main {
    width: 280px !important;
  }
}
</style>
</style>

+ 14 - 0
mini-pro-web/src/router/index.js

@ -10,6 +10,7 @@ import Login from '@/views/login/Login'
import Register from '@/views/login/Register'
import FotgetPassword from '@/views/login/FotgetPassword'
import DrugList from '@/views/drug/list'
import OldDrugList from '@/views/drug/oldList'
import personal from './personal'
import order from './order'
import replenishment from './replenishment'
@ -86,6 +87,19 @@ const routes = [
            }
        }]
    },
    {
        path: '/oldDrugList',
        name: 'oldDrugList',
        component: NavLayout,
        children: [{
            path: '/oldDrugList',
            name: 'oldDrugList',
            component: OldDrugList,
            meta: {
                title: '选择药品'
            }
        }]
    },
    
]

+ 42 - 1
mini-pro-web/src/router/replenishment.js

@ -125,7 +125,6 @@ const routeMap = [
        },
        component: () => import('@/views/replenishment/stockUp/drugList.vue')
      },
      {
        path: '/replenishment/start/deviceList',
        name: 'replenishmentStartDeviceList',
@ -136,6 +135,48 @@ const routeMap = [
        },
        component: () => import('@/views/replenishment/start/deviceList.vue')
      },
      // 旧版 针对大部分药柜
      {
        path: '/replenishment/oldstart/deviceDetail',
        name: 'replenishmentOldStartDeviceDetail',
        meta: {
          title: '药品入库',
          // hasTop: false,
          hasBot: false
        },
        component: () => import('@/views/replenishment/oldStart/deviceDetail.vue')
      },
      {
        path: '/replenishment/oldStart/productDetail',
        name: 'replenishmentOldStartProductDetail',
        meta: {
          title: '药品详情',
          // hasTop: false,
          hasBot: false
        },
        component: () => import('@/views/replenishment/oldStart/productDetail.vue')
      },
      {
        path: '/replenishment/oldStart/quick',
        name: 'replenishmentOldStartQuick',
        meta: {
          title: '药品详情',
          // hasTop: false,
          hasBot: false
        },
        component: () => import('@/views/replenishment/oldStart/quick.vue')
      },
      {
        path: '/replenishment/oldStart/selProduct',
        name: 'replenishmentOldStartSelProduct',
        meta: {
          title: '选择药品',
          // hasTop: false,
          hasBot: false
        },
        component: () => import('@/views/replenishment/oldStart/selProduct.vue')
      },
      // 新版 有追溯码的
      {
        path: '/replenishment/start/deviceDetail',
        name: 'replenishmentStartDeviceDetail',

+ 15 - 1
mini-pro-web/src/views/device/detail.vue

@ -44,7 +44,7 @@
          </div>
          <div>药品申领</div>
        </div>
        <div v-if="hasAuth('replenish')" class="c-t-center" @click="gotoUrl('/replenishment/start/deviceDetail', { deviceId: id })">
        <div v-if="hasAuth('replenish')" class="c-t-center" @click="goDeviceDetail">
          <div>
            <van-image class="ability" :src="require('@/assets/images/buhuo.png')" />
          </div>
@ -266,6 +266,20 @@ export default {
          deviceId: this.id
        })
      }
    },
    goDeviceDetail() {
      const whiteList = ['ff8080817dc1b95c017dc1c9aa560000']
      if (whiteList.indexOf(this.id) > -1) {
        this.$router.push({
          path: '/replenishment/start/deviceDetail',
          query: { deviceId: this.id }
        })
      } else {
        this.$router.push({
          path: '/replenishment/oldStart/deviceDetail',
          query: { deviceId: this.id }
        })
      }
    }
  }
}

+ 129 - 0
mini-pro-web/src/views/drug/oldList.vue

@ -0,0 +1,129 @@
<template>
    <div class="drug-list">
        <van-sticky :offset-top="offsetTop">
            <div class="search">
                <form action="/">
                    <van-search
                        v-model="value"
                        placeholder="至少输入两个关键词进行搜索"
                        show-action
                        @search="getDrugDictionary"
                        @cancel="onCancel"
                        autofocus
                    />
                </form>
            </div>
        </van-sticky>
        <div class="list" v-if="list.length">
            <div 
                v-for="(item, i) in list" :key="i"
                @click="addDrug(item)"
                class="item mb10 bgc-fff btb-e1e1e1 pt10 pb10 plr15">
                <van-row class="lh25 c-333">
                    <span class="fs-17">{{item.drugName}}</span>
                    <span class="fs-14 ml20">药品编码:{{item.drugCode}}</span>
                </van-row>
                <van-row class="lh25">
                    <van-col span="12" class="c-999">规格:<span class="c-333">{{item.specif}}</span></van-col>
                    <van-col span="12" class="c-999">分类:<span class="c-333">{{item.drugClass}}</span></van-col>
                </van-row>
                <van-row class="lh25">
                    <van-col span="24" class="c-999">剂型:<span class="c-333">{{item.dosForm}}</span></van-col>
                    <!-- <van-col span="12" class="c-999">医保支付比例:<span class="c-333"></span></van-col> -->
                </van-row>
                <!-- <van-row class="lh25">
                    <van-col span="12" class="c-999">基药:<span class="c-333"></span></van-col>
                    <van-col span="12" class="c-999">药品类别:<span class="c-333"></span></van-col>
                </van-row> -->
                <!-- <div class="c-ff5e6c fs-14 lh25">高危药品:</div> -->
            </div>
        </div>
        <div v-else class="c-999 fs-14 tc pt20">
            <div v-if="value">搜索不到数据~~</div>
            <div v-else>请输入关键词进行搜索</div>
        </div>
        <SetStockDialog 
            v-model="setStockShow" 
            :trackId="trackId"
            :bussiness="bussiness"
            :drugId="drug.id"
            @onConfirm="onConfirm"/>
            
    </div>
</template>
<script>
import medicineAbinetApi from '@/api/api-medicineAbinet'
import SetStockDialog from '@/views/replenishment/oldStart/components/SetStockDialog'
export default {
    name: "DrugSel",
    components: {
        SetStockDialog
    },
    watch: {
        value(n, o){
            this.getDrugDictionary()
        }
    },
    data(){
        return {
            deviceId: this.$route.query.deviceId,//轨道id
            trackId: this.$route.query.trackId,//轨道id
            value: "",
            list: [],
            setStockShow: false,
            bussiness: this.$route.query.bussiness || '',
            drug: ''
        }
    },
    async created(){
        this.bussiness = this.trackId? 5 : this.bussiness
        this.getDrugDictionary()
    },
    methods: {
        getDrugDictionary(){
            var val = this.value
			if(val&&val.length>=2){
                var p = {
                    content: this.value,
                    userId: this.user.id,
                    deviceId: this.deviceId,
                    page: 1,
                    size: 999
                }
                medicineAbinetApi
                    .getDrugListByDevice(p)
                    .then(res => {
                        if(res.status == 200){
                            this.list = res.detailModelList
                        }
                    })
                    .catch(err=>{
                        console.error(err)
                    })
			}
        },
        onCancel(){
            this.$router.back()
        },
        addDrug(item){
            if(this.trackId || this.bussiness==6){
                this.drug = item
                this.setStockShow = true
                return
            }
            this.$EventBus.$emit('drug-sel', item)
            this.$router.back()
        },
        onConfirm(stock){
            this.drug.upInventory = stock
            this.$EventBus.$emit('drug-sel', this.drug)
            this.$router.back()
        }
    }
};
</script>
<style lang="scss" scoped>
@import './css/drugSel.scss';
</style>

+ 134 - 0
mini-pro-web/src/views/replenishment/oldStart/components/SetStockDialog.vue

@ -0,0 +1,134 @@
<template>
    <div class='replenishment-start-set-stock-dialog  '>
        <van-popup v-model="value" close-on-popstate :close-on-click-overlay="false">
            <div class="plr15 ptb10 c-pr" style="width: 80vw">
                <div class="close fs-20"><van-icon @click="emitValue(false)" name="close" /></div>
                <div class="tc fs-14 c-333">
                    <span>{{bussiness==1? '修改容量' : bussiness==2? '矫正库存' : bussiness==4||bussiness==5? '设置库存' : bussiness==6? '新增' : ''}}</span>
                </div>
                <template v-if="bussiness==1||bussiness==4||bussiness==5||bussiness==6">
                    <div class="tc pt30 pb20"><van-stepper v-model="stock" min="1" max="99" button-size="36px" input-width="60px"/></div>
                </template>
                <div class="tc" v-else>
                    <div class="pt10">
                        <van-image
                            radius="5px"
                            :src="require('@/assets/images/drug_default.png')"
                        />
                    </div>
                    <div class="pt10 c-333 fs-16">{{data.drugName}}</div>
                    <div class="pt10 c-999">软件显示库存:{{data.qty}}</div>
                    <div class="pt10 pb20 ipt plr50">
                        <div class="tc  ">
                            <van-stepper 
                                placeholder="实际库存"
                                v-model="stock" 
                                min="1" 
                                max="99" 
                                button-size="36px" 
                                input-width="60px"/>
                            </div>
                    </div>
                </div>
                <div class="ptb10">
                    <van-button type="info" @click="confirm" size="small" block>确认</van-button>
                </div>
            </div>
        </van-popup>
    </div>
</template>
<script>
import medicineAbinetApi from '@/api/api-medicineAbinet'
export default{
    props:{
        value: {},
        bussiness: {
            default: 1 //1修改容量 2矫正库存 4设置库存 5选择药品后 设置库存  6备药时选择药品
        },
        data: {
            default: function(){
                return {}
            }
        },
        trackId: {default: ""},
        drugId: {default: ""}
    },
    data(){
        return {
            stock: 1
        }
    },
    watch:{
        value:{
            handler(){
                this.stock = this.bussiness==1? this.data.cargoCapacity : this.data.qty 
            },
            immediate: true
        }
    },
    created() {
        
    },
    methods:{
        confirm(){
            if(this.trackId){
                this.updateMediicinecabineInventory()
                return
            }
            this.$emit('onConfirm', this.stock)
        },
        emitValue(show){
            this.$emit('input', show)
        },
        updateMediicinecabineInventory(data){
            this.$loading('保存中..')
            let p = {
                id: this.trackId,
                drugId: this.drugId,
                qty: this.stock,
                userId: this.user.id,
            }
            
            medicineAbinetApi
                .updateMediicinecabineInventory(p)
                .then(res=>{
                    this.setStockShow = false
                    this.$toast.clear()
                    this.$emitRefreshPage('replenishmentOldStartDeviceDetail')
                    history.back()
                    // this.$router.replace({
                    //     path: '/replenishment/start/productDetail',
                    //     query: {
                    //         id: this.trackId
                    //     }
                    // })
                })
                .catch(err=>{
                    console.error(err)
                })
        },
    },
}
</script>
<style lang='scss' scoped>
.replenishment-start-set-stock-dialog{
    .close{
        position: absolute;
        right: 10px;
        top: 10px;
    }
    ::v-deep .van-field{
        padding: 0;
        .van-cell__value{
            border: 1px solid #e1e1e1;
            input{
                text-align: center;
            }
        }
    }
    .van-image{
        width: 200px;
        height: 150px;
    }
}
</style>

+ 761 - 0
mini-pro-web/src/views/replenishment/oldStart/deviceDetail.vue

@ -0,0 +1,761 @@
<template>
    <div class='replenishment-start-device-detail fs-14' :class="{'is-view': isView}">
        <!-- <van-sticky v-if="!isView" :offset-top="offsetTop"> -->
            <div v-if="!isView" class="bgc-17b3ec c-fff">
                <div class="pt10 plr15 ellipsis_1">当前货柜:{{deviceInfo.device.equName}}</div>
                <van-row>
                    <van-col span="8">
                        <div class="tc pt10 pb10">
                            <div class="fs-20">{{deviceInfo.deviceCapacity||0}}</div>
                            <div class="fs-12 pt5">设备容量</div>
                        </div>
                    </van-col>
                    <van-col span="8">
                        <div class="tc pt10 pb10">
                            <div class="fs-20">
                                <span>{{deviceInfo.inStock||0}}</span>
                                <span class="fs-12">/{{((deviceInfo.inStockRate||0) * 100).toFixed(2)}}%</span>
                            </div>
                            <div class="fs-12 pt5">在架库存</div>
                        </div>
                    </van-col>
                    <van-col span="8">
                        <div class="tc pt10 pb10">
                            <div class="fs-20">{{deviceInfo.outOfStock||0}}</div>
                            <div class="fs-12 pt5">缺药库存</div>
                        </div>
                    </van-col>
                </van-row>
                <div class="kitbox fs-12 plr10 pb5">
                    <div class="box-flex-1"> 共:{{deviceInfo.device.layer}}层</div>
                    <div class="box-flex-1 ml5">总货道:{{deviceInfo.totalCargo}}</div>
                    <div class="box-flex-1 ml5">故障:{{faultCount || 0}}</div>
                    <div class="box-flex-1 ml5">关闭:{{deviceInfo.closedCargo || 0}}</div>
                </div>
            </div>
        <!-- </van-sticky> -->
        <div class="fs-14 pl15 ptb10 bgc-fff kitbox">
            <div class="box-flex-1 lh24">
                <span>从上往下数</span>
                <div class="color-block"></div>
                <span class="ml5 fs-12">已关闭</span>
                <div class="color-block ml10 red"></div>
                <span class="ml5 fs-12">故障</span>
            </div>
            <div class="plr15" v-if="!isView&&this.outDetailList&&this.outDetailList.length&&$hasAuth('device', 'operate','replenish')">
                <van-button v-if="curOrder" @click="updateStockUpStatus(curOrder, 2)" type="primary" color="#17b3ec" size="mini">完成入库</van-button>
                <van-button v-else-if="orderList&&orderList.length" @click="showOrderPicker=true" type="primary" color="#17b3ec" size="mini">导入申领药品单</van-button>
            </div>
            <div class="plr15" v-if="isView&&$hasAuth('device', 'operate','replenish')">
                <van-button @click="gotoUrl('/replenishment/start/deviceDetail', {deviceId: deviceId})" type="primary" color="#17b3ec" size="mini">点击进行入库</van-button>
            </div>
        </div>
        <div class=" list-panel">
            <div class="kitbox">
            <div class="left-list">
                <van-sidebar v-model="activeKey">
                    <van-sidebar-item v-for="(item, i) in list" :key="i" :title="i==0? '药品库' : (i)+'层'"  />
                </van-sidebar>
            </div>
            <div class="list box-flex-1 bgc-fff">
                <div v-if="activeKey===0" class="plr10">
                    <div class="search-panel">
                        <form action="/">
                            <van-search
                                v-model="searchText"
                                placeholder="搜索"
                                show-action
                                @search="onSearch"
                                @cancel="onSearch"
                                shape="round">
                            </van-search>
                        </form>
                    </div>
                    <template v-for="(item, k) in curItem.list" >
                        <div v-if="item.isShow" @click="toQuick(item)" class="drug-item kitbox"  :key="k">
                            <div class="sort" v-if="!curOrder" ><div>{{k+1}}</div></div>
                            <div class="photo">
                                <img src="@/assets/images/drug_default.png" alt="">
                            </div>
                            <div class="box-flex-1 pl10">
                                <div class="fs-15 ellipsis_1 c-333">{{item.drugName}}</div>
                                <div class="fs-14 c-666">
                                    <div>编码:{{item.drugCode}}</div>
                                    <div>规格:{{item.specif}}</div>
                                    <div>当前库存量:{{item.qty||item.inventoryNum||Number(item.total||0)}}</div>
                                    <div v-if="curOrder">未放置数量:{{accessLeftNum(item)}}</div>
                                </div>
                            </div>
                        </div>
                    </template>
                </div>
                <template v-else>
                    <template v-for="(item, k) in curItem.list">
                        <div class="item" v-if="item.state!=20" :key="k">
                            <ProductItem :old="true" :bussuness="bussuness" @onChange="onChange($event, item)" :data="item" :index="k" :isView="isView"/>
                        </div>
                    </template>
                </template>
            </div>
            </div>
        </div>
        
        <div class="bot-banner">
            <div class="kitbox">
                <div v-if="!isManage" class="box-flex-1 plr5"><van-button @click="changeManage" block plain color="#17b3ec"  type="primary" round>货道管理</van-button></div>
                <template v-else>
                    <div class="box-flex-1 plr5"><van-button @click="openAndCloseCargo" block plain color="#17b3ec"  type="primary" round>关闭/开启货道</van-button></div>
                    <div class="box-flex-1 plr5"><van-button @click="mergeAndSplitCargo" block plain color="#17b3ec"  type="primary" round>合并/拆分货道</van-button></div>
                    <div class="plr5"><van-button @click="changeManage" class="w50" block plain color="red"  round type="primary" >取消</van-button></div>
                </template>
            </div>
        </div>
        <van-popup v-model="showOrderPicker">
            <div class="tc fs-16 pt15 pb10">药品申领单选择</div>
            <div class="order-list" v-if="orderList&&orderList.length">
                <div class="order-item kitbox ptb10" v-for="item in orderList" :key="item.id">
                    <div class="box-flex-1">
                        <div class="break-all">药品申领单号:{{item.docNum}}</div>
                        <div class="break-all">新增日期:{{item.docTime}}</div>
                        <div class="break-all">申领品类:{{item.replenishCate}}</div>
                        <div class="break-all">申请数量:{{item.replenishInventory}}</div>
                    </div>
                    <div class="pl15 box-v-middle">
                        <van-button @click="updateStockUpStatus(item, 1)" size="mini" type="info">导入</van-button>
                    </div>
                </div>
            </div>
        </van-popup>
    </div>
</template>
<script>
import medicineAbinetApi from '@/api/api-medicineAbinet'
import ProductItem from '@/components/ProductItem'
export default{
    name: 'replenishmentStartOldDeviceDetail',
    components: {
        ProductItem
    },
    props: ['isView'],
    data(){
        return {
            deviceInfo: {device: ''},
            deviceId: this.$route.query.deviceId,
            list: [{
                index: -1,
                list: []
            }],
            activeKey: 0,
            curItem: [],
            openCount: 0,
            closeCount: 0,
            faultCount: 0,
            outDetailList: [],
            deviceDrugList: [],
            showDeviceDrug: true,
            curOrder: '',
            orderList: [],
            showOrderPicker: false,
            selItemList: [],
            isManage: false,
            bussuness: '',
            searchText: ''
        }
    },
    watch:{
        activeKey(n){
            this.curItem = this.list[n]
        }
    },
    created() {
        this.initPage()
        this.findDeviceById()
    },
    methods:{
        $refreshData(){
            this.findMediicinecabinetInventoryByDeviceId()
            this.getDrugInventoryCount()
            if(this.curOrder){
                this.queryUpListByDeviceIdAndStatus()
            }
        },
        async initPage(){
            this.$loading('加载中..')
            await this.queryUpListByDeviceIdAndStatus()
            await this.queryUpListByStatus()
            await this.getDrugInventoryCount()
            await this.getOutDetailByUserIdAndDeviceId()
            this.findMediicinecabinetInventoryByDeviceId()
        },
        checkUpdateStockUpStatus(item, status){
            return new Promise((resolve, reject)=>{
                if(status == 2){
                    this.$dialog.confirm({
                        title: '完成入库',
                        confirmButtonText: "完成入库",
                        message: `请确认药品申领单:${item.docNum} 是否全部完成药品入库,完成后生效并删除此药品申领单`,
                    })
                    .then(() => {
                        resolve(true)
                    })
                    .catch(()=>{
                        resolve(false)
                    })
                } else {
                    resolve(true)
                }
            })
        },
        updateStockUpStatus(item, status){
            this.checkUpdateStockUpStatus(item, status).then(res=>{
                if(!res){
                    return
                }
                this.$toast('加载中..')
                //查备药单详情
                let p = {
                    equNum: this.deviceInfo.device.equNum,
                    id: item.outId || item.id,
                    status
                }
                console.log('updateStockUpStatus', p)
                medicineAbinetApi
                    .updateStockUpStatus(p)
                    .then(res=>{
                        this.$toast.clear()
                        console.log('updateStockUpStatus', res)
                        if(res && res.status == 200){
                            if(status == 1){
                                this.showOrderPicker = false
                                var mediicinestockout = res.obj.mediicinestockout
                                mediicinestockout.outId = res.obj.id
                                this.curOrder = mediicinestockout
                                this.list[0].list = _.filter(this.curOrder.mediicinestockoutdetails, v=>{
                                    v.isShow = true
                                    return this.accessLeftNum(v)>0
                                })
                            } else {
                                this.curOrder = ''
                                this.list[0].list = this.deviceDrugList
                            }
                            this.queryUpListByStatus()
                        }
                    })
                    .catch(err=>{
                        console.error(err)
                    })
            })
        },
        async queryUpListByStatus(){
            //查询已领取 未导入的备药单
            let p = {
                replenishEr: this.user.id,
                deviceId: this.deviceId
            }
            console.log('queryUpListByStatus', p)
            await medicineAbinetApi
                .queryUpListByStatus(p)
                .then(res=>{
                    console.log('queryUpListByStatus', res)
                    this.orderList = res.detailModelList
                })
                .catch(err=>{
                    console.error(err)
                })
        },
        async queryUpListByDeviceIdAndStatus(){
            //查询是否存在未完成备药单
            let p = {
                replenishEr: this.user.id,
                deviceId: this.deviceId
            }
            console.log('queryUpListByDeviceIdAndStatus', p)
            await medicineAbinetApi
                .queryUpListByDeviceIdAndStatus(p)
                .then(res=>{
                    console.log('queryUpListByDeviceIdAndStatus', res)
                    if(res && res.detailModelList && res.detailModelList.length){
                        var mediicinestockout = res.detailModelList[0].mediicinestockout
                        mediicinestockout.outId = res.detailModelList[0].id
                        this.curOrder = mediicinestockout
                        this.list[0].list = _.filter(this.curOrder.mediicinestockoutdetails, v=>{
                            v.isShow = true
                            return this.accessLeftNum(v)>0
                        })
                        console.log(this.list[0])
                    }
                })
                .catch(err=>{
                    console.error(err)
                })
        },
        async getDrugInventoryCount(){
            let p = {
                deviceId: this.deviceId
            }
            console.log('getDrugInventoryCount', p)
            await medicineAbinetApi
                .getDrugInventoryCount(p)
                .then(res=>{
                    console.log('getDrugInventoryCount', res)
                    _.each(res.detailModelList, v=>{
                        v.isShow = true
                    })
                    if(!this.curOrder){
                        this.list[0].list = res.detailModelList 
                    }
                    this.deviceDrugList = res.detailModelList
                })
                .catch(err=>{
                    console.error(err)
                })
        },
        async getOutDetailByUserIdAndDeviceId(){
            let p = {
                deviceId: this.deviceId,
                userId: this.user.id
            }
            console.log('getOutDetailByUserIdAndDeviceId', p)
            await medicineAbinetApi
                .getOutDetailByUserIdAndDeviceId(p)
                .then(res=>{
                    console.log('getOutDetailByUserIdAndDeviceId', res)
                    res.detailModelList.forEach(v=>{
                        var exist = _.find(this.deviceDrugList, m=>{
                            return v.drugCode == m.drugCode
                        })
                        v.qty = (exist&&exist.qty) || 0
                        v.isShow = true
                    })
                    this.outDetailList = res.detailModelList
                })
                .catch(err=>{
                    console.error(err)
                })
        },
        findMediicinecabinetInventoryByDeviceId(){
            this.list.splice(1, this.list.length)
            let p = {
                deviceId: this.deviceId
            }
            console.log('params', p)
            medicineAbinetApi
                .findMediicinecabinetInventoryByDeviceId(p)
                .then(res=>{
                    console.log('findMediicinecabinetInventoryByDeviceId', res)
                    this.$toast.clear()
                    if(res.detailModelList && res.detailModelList.length){
                        var openCount = 0, closeCount = 0, faultCount = 0
                        var list = _.map(res.detailModelList, v=>{
                            var key = _.keys(v)[0]
                            v[key].forEach(m => {
                                m.layerNo = Number(m.layerNo)
                                m.wayerNo = Number(m.wayerNo)
                                m.isActive = false
                                m.cargoState==1? openCount++ : closeCount++
                                if(m.faultState==1){
                                    faultCount++
                                }
                            });
                            return {
                                index: key,
                                list: v[key],
                            }
                        })
                        this.openCount = openCount
                        this.closeCount = closeCount
                        this.faultCount = faultCount
                        list = _.sortBy(list, 'index')
                        this.list = this.list.concat(list)
                        this.curItem = this.list[this.activeKey]
                        console.log(list, this.curItem)
                    }
                })
                .catch(err=>{
                    console.error(err)
                })
        },
        findDeviceById(){
            let p = {
                deviceId: this.deviceId
            }
            console.log('params', p)
            medicineAbinetApi
                .findDeviceById(p)
                .then(res=>{
                    console.log('findDeviceById', res)
                    this.$toast.clear()
                    this.deviceInfo = res.obj
                })
                .catch(err=>{
                    console.error(err)
                })
        },
        changeShowDrug(){
            this.showDeviceDrug = !this.showDeviceDrug
            this.list[0].list = this.showDeviceDrug? this.deviceDrugList : this.outDetailList
        },
        toQuick(item){
            if(this.isView){
                return
            }
            this.gotoUrl('/replenishment/oldStart/quick', {
                deviceId: this.deviceId,
                drugName: item.drugName,
                drugCode: item.drugCode,
                drugId: item.drugId,
                qty: item.qty||item.inventoryNum||Number(item.total||0),
                quantity: this.accessLeftNum(item),  
                outDetailId: item.id,
                specif: encodeURIComponent(item.specif)
            })
        },
        accessLeftNum(item){
            var left = (item.quantity||0) - (item.batchNum||0)
            return left<0? 0 : left
        },
        changeManage(){
            if(this.isManage){
                this.selItemList.forEach(v=>{
                    v.isActive = false
                })
                this.selItemList = []
                this.bussuness = '';
            } else{
                this.bussuness = 'quick';
            }
            this.isManage = !this.isManage
        },
        onChange(isActive, item){
            item.isActive = isActive
            if(isActive){
                this.selItemList.push(item)
            } else {
                this.selItemList.splice(this.selItemList.indexOf(item), 1)
            }
        },
        checkOpenOrClose(){
            return new Promise((resolve, reject)=>{
                var g = _.groupBy(this.selItemList, 'cargoState')
                if(g[1] && g[0]){
                    this.$dialog.confirm({
                        title: '货道设置',
                        message: `选中货道已包含"关闭"和"开启"货道,请选择`,
                        confirmButtonText: '全部开启',
                        cancelButtonText: '全部关闭'
                    })
                    .then(() => {
                        resolve(1)
                    })
                    .catch(()=>{
                        resolve(0)
                    })
                } else {
                    resolve(g[1]? 0 : 1)
                }
            })
        },
        openAndCloseCargo(){
            if(!this.selItemList || !this.selItemList.length){
                this.$toast('请选择要操作的货道')
                return
            }
            this.checkOpenOrClose().then(cargoState=>{
                this.$nextTick(()=>{
                    this.$loading('保存中..')
                    var ids = []
                    this.selItemList.forEach(v=>{
                        if(v.state == 21){
                            var cargoIds = v.merge.split(',')
                            cargoIds.forEach(m => {
                                ids.push(this.list[Number(v.layerNo)].list[Number(m)-1].id)
                            })
                        } else {
                            ids.push(v.id)
                        }
                    })
                    console.log('ids', ids)
                    let p = {
                        cargoIds: ids.join(','),//必穿		货道id,多个id,英文逗号隔开,例如   1,2 		4,5,6
                        cargoState 		//必传		1开启,0关闭
                    }
                    console.log('params', p)
                    medicineAbinetApi
                        .openAndCloseCargo(p)
                        .then(res=>{
                            console.log('openAndCloseCargo', res)
                            this.selItemList.forEach(v=>{
                                v.isActive = false
                                v.cargoState = cargoState
                            })
                            this.selItemList = []
                            this.$toast({
                                message: '操作成功',
                                forbidClick: true,
                                onClose: ()=>{
                                }
                            })
                            this.findDeviceById()
                            this.setBackRefresh(true)
                        })
                        .catch(err=>{
                            console.error(err)
                        })
                })
            })
        },
        checkMerge(){
            return new Promise((resolve, reject)=>{
                var exist = _.find(this.selItemList, v=>{
                    return !!v.drugCode
                })
                if(exist){
                    this.$toast.clear()
                    this.$dialog.confirm({
                        message: '当前合并货道存在药品,需把药品下架并取出,如您继续合并默认下架全部药品',
                        confirmButtonText: '继续合并'
                    })
                    .then(() => {
                        this.$loading('保存中..')
                        resolve(true)
                    })
                    .catch(() => {
                        resolve(false)
                    });
                    return 
                }
                resolve(true)
            })
        },
        checkSplit(){
            return new Promise((resolve, reject)=>{
                this.$toast.clear()
                this.$dialog.confirm({
                    message: '货道拆分后请取下货道上的药品',
                    confirmButtonText: '继续拆分'
                })
                .then(() => {
                    resolve(true)
                })
                .catch(() => {
                    resolve(false)
                });
            })
        },
        async mergeAndSplitCargo(){
            this.$loading('保存中..')
            var ids = []
            var g = _.groupBy(this.selItemList, 'state')
            if((g['21'] || g['20']) && g['1']){
                this.$toast.clear()
                this.$dialog.alert({
                    title: '货道设置',
                    message: `当前选中货道包含合并,您需要先手动拆分合并的货道`,
                    confirmButtonText: '我已知悉',
                })
                return
            }
            var isMerge = g['21']? false : true
            if(isMerge){
                if(!this.selItemList.length || this.selItemList.length<2){
                    this.$toast('至少选择两个相邻的货道')
                    return
                }
                var list = _.sortBy(this.selItemList, ['layerNo', 'wayerNo'])
                var exist = _.find(list, (v, i)=>{
                    var next = list[i+1]
                    if(next){
                        if(next && v.layerNo!=next.layerNo){
                            return true
                        }
                        if(Number(v.wayerNo)+1 != Number(next.wayerNo)){
                            return true
                        }
                    }
                    return false
                })
                console.log(this.selItemList, 'this.selectList')
                if(exist){
                    this.$toast('只能选择相邻的货道进行合并')
                    return 
                }
                if(!await this.checkMerge()){
                    return
                }
                ids = _.map(list, v=>{
                    return v.id
                })
            } else {
                if(!this.selItemList.length || this.selItemList.length>1 || this.selItemList[0].state!=21){
                    this.$toast('请选择一个主货道')
                    return
                }
                if(!await this.checkSplit()){
                    return
                }
                this.$loading('保存中..')
                var item = this.selItemList[0]
                ids.push(item.id)
            }
            
            var p = {
                userId: this.user.id,
                cargoIds: ids.join(','),
                isMerge
            }
            console.log(p)
            medicineAbinetApi
                .mergeAndSplitCargo(p)
                .then(res=>{
                    console.log('mergeAndSplitCargo', res)
                    if(res.status == 200){
                        this.selItemList = []
                        this.$toast('操作成功')
                        this.findDeviceById()
                        this.$refreshData()
                    } 
                })
                .catch(err=>{
                    console.error(err)
                })
        },
        onSearch(){
            _.each(this.list[0].list, v=>{
                v.isShow = v.drugName.indexOf(this.searchText)!=-1
            })
        },
    },
}
</script>
<style lang='scss' scoped>
.replenishment-start-device-detail{
    display: -webkit-box;
    -webkit-box-orient: vertical;
    height: 100vh;
    .list-panel{
        -webkit-box-flex: 1;
        position: relative;
        >.kitbox{
            height: 100%;
            width: 100%;
            position: absolute;
        }
    }
    .list{
        display: flex;
        flex-wrap: wrap;
        align-content: flex-start;
        .item{
            margin-left: 5px;
            margin-bottom: 5px;
            height: 80px;
            .components-product-item{
                width: 90px;
            }
        }
        .drug-item{
            margin-top: 10px;
            img{
                width: 60px;
                border-radius: 5px;
            }
            .sort{
                display: -webkit-box;
                padding-right: 10px;
                padding-top: 20px;
                >div{
                    font-size: 14px;
                    line-height: 20px;
                    width: 20px;
                    height: 20px;
                    background: #17b3ec;
                    border-radius: 50%;
                    color: #fff;
                    text-align: center
                }
            }
        }
    }
    .left-list, .list{
        height: 100%;
        overflow-y: auto;
    }
    .color-block{
        background: #ff9526;
        width: 10px;
        height: 10px;
        display: inline-block;
        margin-left: 20px;
        border-radius: 2px;
        &.red{
            background: #ff5e6c;
        }
    }
    &.is-view{
        .bot-banner{
            display: none;
        }
    }
    .van-popup{
        border-radius: 10px;
    }
    .order-list{
        max-height: 50vh;
        overflow-y: auto;
        padding: 0 15px;
        width: 80vw;
        .order-item{
            border-bottom: 1px solid #e1e1e1;
            &:last-child{
                border-bottom: 0;
            }
        }
    }
    .bot-banner{
        padding: 10px 5px;
        position: relative;
        bottom: 0;
        width: 100%;
        left: 0;
        background: #fff;
        z-index: 3;
        >div{
            -webkit-box-flex: 1;
            .van-button{
                padding: 0;
                font-size: 13px;
                height: 36px;
            }
        }
    }
}
</style>
<style lang="scss">
.mainNobotHasTop{
    .replenishment-start-device-detail{
        height: calc(100vh - 46px);
    }
}
@supports(bottom: env(safe-area-inset-bottom)){
    .replenishment-start-device-detail{
        .bot-banner{
            &::after{
                content: "";
                height: env(safe-area-inset-bottom);
                width: 100%;
                display: block;
            }
        }
    }
}
</style>

+ 132 - 0
mini-pro-web/src/views/replenishment/oldStart/deviceList.vue

@ -0,0 +1,132 @@
<template>
<div class='replenishment-start-device-list'>
    <van-sticky :offset-top="offsetTop">
        <van-tabs v-model="active">
            <van-tab title="缺药设备"></van-tab>
            <van-tab title="全部设备"></van-tab>
        </van-tabs>
    </van-sticky>
    <CustomList 
        ref="customList"
        @onLoad="onLoad">
        <div class="list plr15 pt10">
            <div v-for="(item, i) in list" :key="i" class="item bgc-fff plr15 c-333 fs-14">
                <div class=" ptb10 kitbox">
                    <div class="box-flex-1 fs-14">
                        {{item.equName}}
                    </div>
                    <div class="">
                        <van-tag v-if="item.networkStatus==1" type="success">在线</van-tag>
                        <van-tag v-else type="danger">离线</van-tag>
                        <van-tag class="ml5" v-if="item.saleStatus==1" type="success">在售</van-tag>
                        <van-tag class="ml5" v-else type="danger">停售</van-tag>
                    </div>
                </div>
                <div class="lh20 ptb10 kitbox">
                    <div class="box-flex-1">
                        <div>设备编号:{{item.equNum}}</div>
                        <div>上次补货时间:{{item.shangyicibuhuoshijian}}</div>
                    </div>
                </div>
                <div class="operate pt10 pb10">
                    <van-button round block @click="gotoUrl('./deviceDetail', {deviceId: item.id})" type="info" size="small" >开始补货</van-button>
                </div>
            </div>
        </div>
    </CustomList>
</div>
</template>
<script>
import medicineAbinetApi from '@/api/api-medicineAbinet'
export default{
    name: 'replenishmentOldStartDeviceList',
    data(){
        return {
            list: [],
            result: [],
            selAll: false,
            active: 0
        }
    },
    watch:{
        active(){
            this.$refs.customList.refresh(true)
        }
    },
    created() {
        
    },
    methods:{
        onLoad({page, pageSize, searchText}){
            var p = {
                content: searchText,
                userId: this.user.id,
                page: page,
                size: pageSize
            }
            var func
            if(this.active === 0){
                func = medicineAbinetApi.getOutOfStockDeviceListByUserId
            } else {
                func = medicineAbinetApi.getDeviceListWithUserId
            }
            func(p)
                .then(res=>{
                    if(res.status == 200){
                        var list = res.detailModelList
                        this.list = page==1? list : this.list.concat(list)
                        this.$refs.customList.endLoad(res.totalPage<=page || this.active===0, this.list.length)
                    } else {
                        this.list = []
                        this.$refs.customList.endLoad(false, true)
                    }
                }).catch(err=>{
                    console.error(err)
                    this.list = []
                    this.$refs.customList.endLoad(false, true)
                })
        },
    },
}
</script>
<style lang='scss' scoped>
.replenishment-start-device-list{
    ::v-deep .custom-list .search{
        top: 50px;
    }
    .list{
        .item{
            margin-bottom: 10px;
            border-radius: 5px;
            &:last-child{
                margin-bottom: 0;
            }
            .van-icon{
                position: absolute;
                top: 50%;
                transform: translateY(calc(-50% - 15px));
                right: 0;
                color: #ccc;
            }
        }
    }   
    .operate{
        >div{
            // width: 50%;
        }
    }
}
</style>
<style lang="scss">
.mainNobotHasTop{
    .replenishment-start-device-list{
        .custom-list {
            height: calc(100vh - 96px);
            .search{
                top: 96px;
            }
        }
    }
}
</style>

+ 253 - 0
mini-pro-web/src/views/replenishment/oldStart/productDetail.vue

@ -0,0 +1,253 @@
<template>
    <div class='replenishment-start-product-detail fs-14' v-if="info">
        <div class="tc pt50">
            <van-image
                radius="5px"
                :src="require('@/assets/images/drug_default.png')"
            />
        </div>
        <div class="tc c-333 pt20 pb10 plr15 break-all">{{info.drugName}}</div>
        <div class="tc c-333 pt20 pb10 plr15 break-all">{{info.specif}}</div>
        <div class="c-17b3ec tc"><span @click="gotoUrl('/oldDrugList', {deviceId: info.idDevice})">更换药品</span></div>
        <div class=" tc pt20">
            <span class="mr10">现有数量:{{info.qty}} </span>
            <span class="ml10">货道容量:{{info.cargoCapacity}} </span>
        </div>
        <div class="pt20">
            <div class="progress">
                <div class="bar" :style="'width:'+ (rate) +'%'"></div>
                <div class="text">{{info.qty}}/{{info.cargoCapacity}}</div>
            </div>
        </div>
        <div class="bot-banner  ptb10">
            <div><van-button type="info" @click="bussiness=2;setStockShow=true" round block >矫正库存</van-button></div>
            <div class="kitbox pt10">
                <div class="box-flex-1 pr10"><van-button @click="bussiness=1;setStockShow=true" type="info" round block plain >修改容量</van-button></div>
                <div class="box-flex-1 pl10"><van-button @click="checkRemoveDrug()" type="info" round block plain class="red" >下架药品</van-button></div>
            </div>
        </div>
        <!-- 修改容量 -->
        <SetStockDialog 
            v-model="setStockShow" 
            :data="info"
            @onConfirm="updateMediicinecabineInventoryInfoById" 
            :bussiness="bussiness"/>
    </div>
</template>
<script>
import medicineAbinetApi from '@/api/api-medicineAbinet'
import SetStockDialog from './components/SetStockDialog'
export default{
    name: 'replenishmentOldStartProductDetail',
    components:{
        SetStockDialog
    },
    data(){
        return {
            id: this.$route.query.id,
            shelfStatus: this.$route.query.shelfStatus,
            setStockShow: false,
            info: '',
            bussiness: 1, //1修改容量 2矫正库存 3上下架
            drugId: '',
            drugName: '',
            drugPrice: '',
            from: this.$route.query.from,
        }
    },
    computed:{
        rate(){
            var {info} = this
            return (info&&(Number(info.qty) / Number(info.cargoCapacity) * 100))|| 0
        }
    },
    created() {
        this.$EventBus.$on('drug-sel', data=>{
            this.drugId = data.id
            this.drugName = data.drugName
            this.drugPrice = data.price
            this.bussiness = 4
            this.setStockShow = true
        })
        this.selectMediicinecabineInventoryById()
    },
    beforeDestroy(){
        this.$EventBus.$off('drug-sel')
    },
    methods:{
        selectMediicinecabineInventoryById(){
            this.$loading('加载中..')
            let p = {
                id: this.id
            }
            console.log('params', p)
            medicineAbinetApi
                .selectMediicinecabineInventoryById(p)
                .then(res=>{
                    this.$toast.clear()
                    this.info = res.obj
                })
                .catch(err=>{
                    console.error(err)
                })
        },
        checkRemoveDrug(){
            this.$dialog.confirm({
                title: '提示',
                message: '确认下架该药品?',
            })
            .then(() => {
                this.updateMediicinecabineInventoryInfoById(0, 3)
            })
        },
        updateMediicinecabineInventoryInfoById(data, bussiness){
            if(this.bussiness == 4){
                this.updateMediicinecabineInventory(data)
                return
            }
            this.$loading('保存中..')
            let p = {
                id: this.id,
                userId: this.user.id,
            }
            if(bussiness==3){
                p.status = data //下架状态0,上架状态1
            } else if(this.bussiness == 1){
                p.cargoCapacity = data
            } else if(this.bussiness == 2){
                p.qty = data
            } 
            console.log('params', p)
            medicineAbinetApi
                .updateMediicinecabineInventoryInfoById(p)
                .then(res=>{
                    this.setStockShow = false
                    this.$toast.clear()
                    this.$emitRefreshPage('replenishmentOldStartDeviceDetail')
                    this.$emitRefreshPage('replenishmentOldDeviceDetail')
                    if(this.from == 'quick'){
                        this.$emitRefreshPage('replenishmentOldStartQuick', {
                            data,
                            bussiness: bussiness || this.bussiness
                        })
                    }
                    if(bussiness==3){
                        this.$router.back()
                    } else {
                        this.selectMediicinecabineInventoryById()
                    }
                })
                .catch(err=>{
                    console.error(err)
                })
        },
        updateMediicinecabineInventory(data){
            this.$loading('保存中..')
            let p = {
                id: this.id,
                drugId: this.drugId,
                qty:data,
                userId: this.user.id,
            }
            
            console.log('params', p)
            medicineAbinetApi
                .updateMediicinecabineInventory(p)
                .then(res=>{
                    this.setStockShow = false
                    this.$toast.clear()
                    this.$emitRefreshPage('replenishmentOldStartDeviceDetail')
                    this.$emitRefreshPage('replenishmentOldDeviceDetail')
                    this.selectMediicinecabineInventoryById()
                    if(this.from == 'quick'){
                        this.$emitRefreshPage('replenishmentOldStartQuick', {
                            drugId: this.drugId,
                            drugName: this.drugName,
                            drugPrice: this.drugPrice,
                            data,
                            bussiness: 4
                        })
                        history.go(-1)
                    }
                })
                .catch(err=>{
                    console.error(err)
                })
        },
    },
}
</script>
<style lang='scss' scoped>
.replenishment-start-product-detail{
    .van-image{
        width: 100px;
        height: 100px;
    }
    .progress{
        width: 80vw;
        background: #bbb;
        height: 20px;
        border-radius: 20px;
        margin: 0 auto  ;
        position: relative;
        overflow: hidden;
        .bar{
            background: #17b3ec;
            height: 100%;
            display: inline-block;
            color: #fff;
            text-align: center;
            border-top-left-radius: 20px;
            border-bottom-left-radius: 20px;
            line-height: 20px;
        }
        .text{
            position: absolute;
            left: 0;
            top: 0;
            width: 100%;
            background: transparent;
            text-align: center;
            color: #fff;
            line-height: 20px;
        }
        &.full{
            .bar{
                border-radius: 20px;
            }
        }
    }
    .bot-banner{
        position: fixed;
        bottom: 0;
        width: 80%;
        left: 10%;
        // background: #fff;
        .van-button--plain{
            &.red{
                color: #ff5e6c;
                border-color: #ff5e6c;
            }
        }
        .van-button{
            padding: 0;
            font-size: 13px;
            height: 36px;
        }
    }
}
</style>
<style lang='scss'>
@supports(bottom: env(safe-area-inset-bottom)){
    .replenishment-start-product-detail{
        .bot-banner{
            bottom: env(safe-area-inset-bottom) !important;
        }
    }
}
</style>

+ 636 - 0
mini-pro-web/src/views/replenishment/oldStart/quick.vue

@ -0,0 +1,636 @@
<template>
    <div class='replenishment-start-quick fs-14'>
        <div class="plr10 bgc-fff ptb10">
            <div class="drug-item kitbox" :key="k">
                <div class="photo">
                    <img src="@/assets/images/drug_default.png" alt="">
                </div>
                <div class="box-flex-1 pl10">
                    <div class="fs-15 ellipsis_1 c-333">{{query.drugName}}</div>
                    <div class="fs-14 c-666 kitbox">
                        <div class="box-flex-1">
                            <div>规格:{{decodeStr(query.specif)}}</div>
                            <div>当前库存量:{{query.qty}}</div>
                            <div v-if="outDetailId">未放置数量:{{query.quantity}}</div>
                        </div>
                        <div class="stepper kitbox">
                            <van-stepper v-model="num" integer min="0" max="99" />
                            <div v-if="repAll" class="text">补满</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="fs-14 pl15 ptb10 bgc-fff kitbox pr15">
            <div class="box-flex-1 lh24">
                <span>从上往下数</span>
                <div class="color-block"></div>
                <span class="ml5 fs-12">已关闭</span>
                <div class="color-block ml10 red"></div>
                <span class="ml5 fs-12">故障</span>
            </div>
            <div class="c-17B3EC" @click="selectAll" v-if="!isSelectAll">全选</div>
            <div class="c-17B3EC" @click="cancelAll" v-else>取消</div>
        </div>
        <div class="list-panel">
            <div class="kitbox ">
                <div class="left-list">
                    <van-sidebar v-model="activeKey">
                        <van-sidebar-item v-for="(item, i) in list" :key="i" :title="(i+1)+'层'"  />
                    </van-sidebar>
                </div>
                <div class="list box-flex-1 bgc-fff">
                    <template v-if="curItem">
                        <template v-for="(item, k) in curItem.list">
                            <div class="item" v-if="item.state!=20 && (item.drugCode == query.drugCode || !item.drugCode)" :key="k">
                                <ProductItem v-longpress="()=>{gotoDetail(item)}" bussuness="quick" @onChange="onChange($event, item)" :data="item" :index="k"/>
                            </div>
                        </template>
                        <!-- <div class="item" v-for="(item, k) in curItem.list" :key="k">
                            <ProductItem v-if="item.state!=20" bussuness="quick" @onChange="onChange($event, item)" :data="item" :index="k"/>
                        </div> -->
                    </template>
                </div>
            </div>
        </div>
        <div class="bot-banner">
            <div class="kitbox">
                <div class="box-flex-1 plr5"><van-button @click="openAndCloseCargo" block plain color="#17b3ec"  type="primary" round>关闭/开启货道</van-button></div>
                <div class="box-flex-1 plr5"><van-button @click="mergeAndSplitCargo" block plain color="#17b3ec"  type="primary" round>合并/拆分货道</van-button></div>
                <div class="box-flex-1 plr5"><van-button @click="sumit" block color="#17b3ec"  type="primary"  round>完成补货({{allNum}})</van-button></div>
            </div>
        </div>
    </div>
</template>
<script>
import medicineAbinetApi from '@/api/api-medicineAbinet'
import ProductItem from '@/components/ProductItem'
export default{
    name: 'replenishmentOldStartQuick',
    components: {
        ProductItem
    },
    data(){
        return {
            num: 0,
            query: this.$route.query,
            selItemList: [],
            allNum: 0,
            curCargo: '',
            deviceId: this.$route.query.deviceId,
            list: [],
            activeKey: 0,
            curItem: [],
            repAll: true,
            outDetailId: this.$route.query.outDetailId || '',
            isSelectAll: false
        }
    },
    watch:{
        activeKey(n){
            this.curItem = ''
            this.$nextTick(()=>{
                this.curItem = this.list[n]
                this.calIsSelectAll()
            })
        },
        num(n, o){
            this.repAll = false
            this.accessNum()
        }
    },
    created() {
        this.initPage()
    },
    methods:{
        decodeStr(str){
            return (str&&decodeURIComponent(str)) || ""
        },
        $refreshData(p){
            if(p){
                var oQty = this.curCargo.cargoCapacity - this.curCargo.qty
                //1修改容量 2矫正库存 3下架药品  4更换药品
                switch(Number(p.bussiness)){
                    case 1: 
                    case 2: 
                        if(p.bussiness==1){
                            // 1修改容量
                            this.curCargo.cargoCapacity = p.data
                            if(this.curCargo.qty > this.curCargo.cargoCapacity){
                                this.curCargo.qty = this.curCargo.cargoCapacity
                            }
                        } else {
                            // 2矫正库存
                            this.curCargo.qty = p.data
                            if(this.curCargo.qty > this.curCargo.cargoCapacity){
                                this.curCargo.cargoCapacity = this.curCargo.qty
                            }
                        }
                        
                        if(this.curCargo.isActive){
                            this.allNum = this.allNum - oQty + (this.curCargo.cargoCapacity - this.curCargo.qty)
                        }
                        break;
                    case 3: 
                        // 3下架药品 
                        this.curCargo.shelfStatus = 0
                        this.curCargo.qty = 0
                        if(this.curCargo.isActive){
                            this.allNum = this.allNum - oQty + this.curCargo.cargoCapacity
                        }
                        break;
                    case 4: 
                        // 4更换药品
                        this.curItem.list.splice(this.curItem.list.indexOf(this.curCargo), 1)
                        if(this.curCargo.isActive){
                            this.allNum = this.allNum - oQty
                        }
                        break;
                }
            } else {
                this.findMediicinecabinetInventoryByDeviceId()
            }
        },
        initPage(){
            this.findMediicinecabinetInventoryByDeviceId()
        },
        findMediicinecabinetInventoryByDeviceId(){
            this.$loading('加载中..')
            let p = {
                deviceId: this.deviceId
            }
            console.log('params', p)
            medicineAbinetApi
                .findMediicinecabinetInventoryByDeviceId(p)
                .then(res=>{
                    console.log('findMediicinecabinetInventoryByDeviceId', res)
                    this.$toast.clear()
                    if(res.detailModelList && res.detailModelList.length){
                        var list = _.map(res.detailModelList, v=>{
                            var key = _.keys(v)[0]
                            return {
                                index: key,
                                list: _.filter(v[key], m=>{
                                    m.layerNo = Number(m.layerNo)
                                    m.wayerNo = Number(m.wayerNo)
                                    m.isActive = false
                                    return true
                                    return m.drugCode == this.query.drugCode || !m.drugCode
                                }),
                            }
                        })
                        list = _.sortBy(list, 'index')
                        this.list = list
                        this.curItem = this.list[this.activeKey]
                        console.log(list, this.curItem)
                    }
                })
                .catch(err=>{
                    console.error(err)
                })
        },
        onChange(isActive, item){
            var num = this.accessItemNum(item)
            item.isActive = isActive
            if(isActive){
                this.selItemList.push(item)
                this.allNum += num
            } else {
                this.selItemList.splice(this.selItemList.indexOf(item), 1)
                this.allNum -= num
            }
            this.calIsSelectAll()
        },
        calIsSelectAll() {
            let flag = true
            this.list[this.activeKey].list.forEach(el=>{
                if(el.cargoState==1&&!el.isActive){
                    flag = false
                }
            })
            this.isSelectAll = flag
        },
        accessItemNum(item){
            var num = 0
            if(this.repAll){
                num += item.cargoCapacity - item.qty
            } else {
                if(this.num - item.qty > 0){
                    num += (this.num - item.qty)
                }
            }
            return num
        },
        accessNum(){
            var num = 0
            this.selItemList.forEach(v=>{
                num += this.accessItemNum(v)
            })
            this.allNum = num
        },
        sumit(){
            if(!this.selItemList || !this.selItemList.length){
                this.$toast("请选择操作货道")
                return
            }
            if(!this.repAll){
                var exist = _.find(this.selItemList, v=>{
                    return v.qty > this.num
                })
                if(exist){
                    this.$dialog.alert({
                        title: '补货设置',
                        message: `补货数量不能小于当前货道库存,请重新选择数量进行补货`,
                        confirmButtonText: '我已知悉',
                    })
                    return
                }
            }
            if(this.outDetailId && this.query.quantity<this.allNum){
                this.$toast('当前补货数量超过了未放置数量,请重新设置')
                return
            }
            this.$dialog.confirm({
                title: '补货设置',
                message: `确定进行补货?`,
                confirmButtonText: '确定',
            })
            .then(() => {
                var list = _.map(this.selItemList, v=>{
                    return {
                        cargoId: v.id,
                        drugId: this.query.drugId,
                        qty: this.repAll? Number(v.cargoCapacity) : this.num
                    }
                }) 
                this.$nextTick(()=>{
                    this.$loading('保存中..')
                    let p = {
                        list: JSON.stringify({list: list}),
                        userId: this.user.id,
                        outDetailId: this.outDetailId
                    }
                    console.log('params', p)
                    medicineAbinetApi
                        .batchAddInventory(p)
                        .then(res=>{
                            this.query.qty += this.allNum
                            this.query.quantity -= this.allNum
                            if(this.query.quantity<0){
                                this.query.quantity = 0
                            }
                            this.allNum = 0
                            this.selItemList.forEach(v=>{
                                v.isActive = false
                            })
                            this.selItemList = []
                            this.$toast({
                                message: '操作成功',
                                forbidClick: true,
                                onClose: ()=>{
                                    
                                }
                            })
                            this.setBackRefresh(true)
                            this.$refreshData()
                        })
                        .catch(err=>{
                            console.error(err)
                        })
                })
            })
            var exist = _.find(this.selItemList, v=>{
                return v.faultState == 1
            })
            // if(exist){
            //     this.$toast('所选货道存在故障货道')
            //     return
            // }
            // batchAddInventory
        },
        checkOpenOrClose(){
            return new Promise((resolve, reject)=>{
                var g = _.groupBy(this.selItemList, 'cargoState')
                if(g[1] && g[0]){
                    this.$dialog.confirm({
                        title: '货道设置',
                        message: `选中货道已包含"关闭"和"开启"货道,请选择`,
                        confirmButtonText: '全部开启',
                        cancelButtonText: '全部关闭'
                    })
                    .then(() => {
                        resolve(1)
                    })
                    .catch(()=>{
                        resolve(0)
                    })
                } else {
                    resolve(g[1]? 0 : 1)
                }
            })
        },
        openAndCloseCargo(){
            if(!this.selItemList || !this.selItemList.length){
                this.$toast('请选择要操作的货道')
                return
            }
            this.checkOpenOrClose().then(cargoState=>{
                this.$nextTick(()=>{
                    this.$loading('保存中..')
                    var ids = []
                    this.selItemList.forEach(v=>{
                        if(v.state == 21){
                            var cargoIds = v.merge.split(',')
                            cargoIds.forEach(m => {
                                ids.push(this.list[Number(v.layerNo)-1].list[Number(m)-1].id)
                            })
                        } else {
                            ids.push(v.id)
                        }
                    })
                    console.log('ids', ids)
                    let p = {
                        cargoIds: ids.join(','),//必穿		货道id,多个id,英文逗号隔开,例如   1,2 		4,5,6
                        cargoState 		//必传		1开启,0关闭
                    }
                    medicineAbinetApi
                        .openAndCloseCargo(p)
                        .then(res=>{
                            console.log('openAndCloseCargo', res)
                            this.selItemList.forEach(v=>{
                                v.isActive = false
                                v.cargoState = cargoState
                            })
                            this.selItemList = []
                            this.$toast({
                                message: '操作成功',
                                forbidClick: true,
                                onClose: ()=>{
                                }
                            })
                            this.setBackRefresh(true)
                        })
                        .catch(err=>{
                            console.error(err)
                        })
                })
            })
        },
        checkMerge(){
            return new Promise((resolve, reject)=>{
                var exist = _.find(this.selItemList, v=>{
                    return !!v.drugCode
                })
                if(exist){
                    this.$toast.clear()
                    this.$dialog.confirm({
                        message: '当前合并货道存在药品,需把药品下架并取出,如您继续合并默认下架全部药品',
                        confirmButtonText: '继续合并'
                    })
                    .then(() => {
                        this.$loading('保存中..')
                        resolve(true)
                    })
                    .catch(() => {
                        resolve(false)
                    });
                    return 
                }
                resolve(true)
            })
        },
        checkSplit(){
            return new Promise((resolve, reject)=>{
                this.$toast.clear()
                this.$dialog.confirm({
                    message: '货道拆分后请取下货道上的药品',
                    confirmButtonText: '继续拆分'
                })
                .then(() => {
                    resolve(true)
                })
                .catch(() => {
                    resolve(false)
                });
            })
        },
        async mergeAndSplitCargo(){
            this.$loading('保存中..')
            var ids = []
            var g = _.groupBy(this.selItemList, 'state')
            if((g['21'] || g['20']) && g['1']){
                this.$toast.clear()
                this.$dialog.alert({
                    title: '货道设置',
                    message: `当前选中货道包含合并,您需要先手动拆分合并的货道`,
                    confirmButtonText: '我已知悉',
                })
                return
            }
            var isMerge = g['21']? false : true
            if(isMerge){
                if(!this.selItemList.length || this.selItemList.length<2){
                    this.$toast('至少选择两个相邻的货道')
                    return
                }
                var list = _.sortBy(this.selItemList, ['layerNo', 'wayerNo'])
                var exist = _.find(list, (v, i)=>{
                    var next = list[i+1]
                    if(next){
                        if(next && v.layerNo!=next.layerNo){
                            return true
                        }
                        if(Number(v.wayerNo)+1 != Number(next.wayerNo)){
                            return true
                        }
                    }
                    return false
                })
                if(exist){
                    this.$toast('只能选择相邻的货道进行合并')
                    return 
                }
                if(!await this.checkMerge()){
                    return
                }
                ids = _.map(list, v=>{
                    return v.id
                })
            } else {
                if(!this.selItemList.length || this.selItemList.length>1 || this.selItemList[0].state!=21){
                    this.$toast('请选择一个主货道')
                    return
                }
                if(!await this.checkSplit()){
                    return
                }
                this.$loading('保存中..')
                var item = this.selItemList[0]
                ids.push(item.id)
            }
            
            var p = {
                userId: this.user.id,
                cargoIds: ids.join(','),
                isMerge
            }
            medicineAbinetApi
                .mergeAndSplitCargo(p)
                .then(res=>{
                    console.log('mergeAndSplitCargo', res)
                    if(res.status == 200){
                        this.selItemList = []
                        this.$toast('操作成功')
                        this.$refreshData()
                        this.setBackRefresh(true)
                    } 
                })
                .catch(err=>{
                    console.error(err)
                })
        },
        gotoDetail(item){
            if(item.shelfStatus==1){
                this.curCargo = item; 
                this.gotoUrl('./productDetail', {
                    id: item.id,
                    from: 'quick'
                })
            }
        },
        selectAll(){
            this.isSelectAll = true
            this.list[this.activeKey].list.forEach(el=>{
                if(this.selItemList.findIndex(item=>{return item.id == el.id})<0&&el.cargoState==1){
                    el.isActive = true
                    this.selItemList.push(el)
                    const num = this.accessItemNum(el)
                    this.allNum += num
                }
            })
        },
        cancelAll(){
            this.isSelectAll = false
            this.list[this.activeKey].list.forEach(el=>{
                const index = this.selItemList.findIndex(item=>{return item.id == el.id})
                if(index > -1){
                    el.isActive = false
                    this.selItemList.splice(index, 1)
                    const num = this.accessItemNum(el)
                    this.allNum -= num
                }
            })
        }
    },
}
</script>
<style lang='scss' scoped>
.replenishment-start-quick{
    display: -webkit-box;
    -webkit-box-orient: vertical;
    height: 100vh;
    .list-panel{
        -webkit-box-flex: 1;
        position: relative;
        >.kitbox{
            height: 100%;
            width: 100%;
            position: absolute;
        }
    }
    .drug-item{
        img{
            width: 60px;
            border-radius: 5px;
        }
        .stepper{
            -webkit-box-align: end;
            position: relative;
            .text{
                position: absolute;
                background: #f2f3f5;
                width: 34px;
                text-align: center;
                left: 50%;
                transform: translateX(-50%);
                bottom: 0;
                line-height: 27px;
            }
        }
    }
    .list{
        display: flex;
        flex-wrap: wrap;
        align-content: flex-start;
        .item{
            margin-left: 5px;
            margin-bottom: 5px;
            height: 80px;
            .components-product-item{
                width: 90px;
            }
        }
        
    }
    .left-list, .list{
        height: 100%;
        overflow-y: auto;
    }
    .color-block{
        background: #ff9526;
        width: 10px;
        height: 10px;
        display: inline-block;
        margin-left: 20px;
        border-radius: 2px;
        &.red{
            background: #ff5e6c;
        }
    }
    .bot-banner{
        padding: 10px 5px;
        position: relative;
        bottom: 0;
        width: 100%;
        left: 0;
        background: #fff;
        z-index: 3;
        >div{
            -webkit-box-flex: 1;
            .van-button{
                padding: 0;
                font-size: 13px;
                height: 36px;
            }
        }
    }
}
</style>
<style lang="scss">
.mainNobotHasTop{
    .replenishment-start-quick{
        height: calc(100vh - 46px);
    }
}
@supports(bottom: env(safe-area-inset-bottom)){
    .replenishment-start-quick{
        .bot-banner{
            &::after{
                content: "";
                height: env(safe-area-inset-bottom);
                width: 100%;
                display: block;
            }
        }
    }
}
</style>

+ 102 - 0
mini-pro-web/src/views/replenishment/oldStart/selProduct.vue

@ -0,0 +1,102 @@
<template>
    <div class='replenishment-start-sel-product fs-14'>
        <form action="/">
            <van-search
                v-model="searchText"
                show-action
                placeholder="请输入药品名称搜索"
                @search="onSearch"
                @cancel="onCancel"
            />
        </form>
        <div v-if="!inSearch" class="kitbox bt-e1e1e1">
            <div>
                <van-sidebar v-model="activeKey">
                    <van-sidebar-item title="全部分类"  />
                    <van-sidebar-item title="默认分类"  />
                </van-sidebar>
            </div>
            <div class="list box-flex-1 bgc-fff pb10">
                <div class="item plr10 pt10" v-for="i in 5" :key="i">
                    <div class="kitbox">
                        <div class="photo">
                            <van-image radius="5px" src="https://img01.yzcdn.cn/vant/cat.jpeg"/>
                        </div>
                        <div class="box-flex-1 pl10 right" >
                            <div class="fs-14 c-333">J氯化钠注射液(90mg)</div>
                            <div class="fs-12 c-999">
                                <div>药品条码:12464</div>
                                <div>价格:¥27.00  <span class="ml5">规格:0.33g*27</span></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div v-else class="list box-flex-1 bgc-fff pb10">
            <div class="item plr10 pt10" v-for="i in 5" :key="i">
                <div class="kitbox">
                    <div class="photo">
                        <van-image radius="5px" src="https://img01.yzcdn.cn/vant/cat.jpeg"/>
                    </div>
                    <div class="box-flex-1 pl10 right" >
                        <div class="fs-14 c-333">J氯化钠注射液(90mg)</div>
                        <div class="fs-12 c-999">
                            <div>药品条码:12464</div>
                            <div>价格:¥27.00  <span class="ml5">规格:0.33g*27</span></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <SetStockDialog v-model="setStockShow" />
    </div>
</template>
<script>
import SetStockDialog from './components/SetStockDialog'
export default{
    name: 'replenishmentOldStartSelProduct',
    components:{
        SetStockDialog
    },
    data(){
        return {
            activeKey: 0,
            searchText: '',
            inSearch: false,
            setStockShow: false,
        }
    },
    created() {
        
    },
    methods:{
        onSearch(){
        },
        onCancel(){
        }
    },
}
</script>
<style lang='scss' scoped>
.replenishment-start-sel-product{
    .list{
        .item{
            .photo{
                .van-image{
                    width: 50px;
                    height: 50px;
                    display: block;
                }
            }
            .right{
                margin-top: -2px;
            }
        }
    }
}
</style>

+ 3 - 0
mini-pro-web/src/views/replenishment/start/productDetail.vue

@ -103,6 +103,9 @@ export default {
    })
    this.selectMediicinecabineInventoryById()
  },
  beforeDestroy(){
    this.$EventBus.$off('drug-sel')
  },
  methods: {
    drugTraceabilityCodeDetail(deviceId, drugId, trackId) {
      const params = {