Pārlūkot izejas kodu

Merge branch '套餐商城'

lighter 5 mēneši atpakaļ
vecāks
revīzija
270546952b

+ 8 - 0
src/api/outpatient/wxmall-package.js

@@ -8,6 +8,14 @@ export function getPackagesByCondition(data) {
   })
 }
 
+export function getOriginPrice(type,code) {
+  return request({
+    url: '/wxmallPackage/getOriginPrice',
+    method: 'get',
+    params: {type,code}
+  })
+}
+
 export function createNewPackage2(data) {
   return request({
     url: '/wxmallPackage/createNewPackage2',

+ 16 - 1
src/components/search/Index.vue

@@ -19,6 +19,16 @@
             ></el-option>
           </el-select>
         </div>
+        <div v-if="showMallType" style="margin-left: 4px">
+          项目类别:
+        </div>
+        <div v-if="showMallType">
+          <el-select v-model="params.target" style="width: 60px">
+            <el-option label="检验" value="JY" />
+            <el-option label="检查" value="JC" />
+            <el-option label="诊疗" value="ZL" />
+          </el-select>
+        </div>
         <div>
           <el-input
               ref="inputRef"
@@ -115,6 +125,10 @@ const props = defineProps({
   showOpType: {
     type: Boolean,
     default: false
+  },
+  showMallType: {
+    type: Boolean,
+    default: false
   }
 })
 
@@ -179,7 +193,8 @@ const clickItem = (item) => {
     diagItem.icdText = item.name
     diagItem.diagType = '1'
     showDiagType.value = true
-  } else {
+  } else if (props.showMallType) {
+    item.type = params.target
     emits('clickItem', item)
   }
 }

+ 138 - 26
src/views/clinic/wx-business/WxmallPackage.vue

@@ -2,25 +2,26 @@
   <div class="layout_container wxmall-package">
     <header class="round-header">
       <span>上架时间:</span>
-      <CyDateRange />
+      <CyDateRange/>
       <span class="ml-12">
         套餐状态:
       </span>
       <el-select v-model="inquiry.state" clearable class="w-80">
-        <el-option label="已上架" value="ACTIVATED" />
-        <el-option label="已下架" value="DEACTIVATED" />
+        <el-option label="已上架" value="ACTIVATED"/>
+        <el-option label="已下架" value="DEACTIVATED"/>
       </el-select>
-      <el-divider direction="vertical" />
+      <el-divider direction="vertical"/>
       <el-button icon="Search" type="primary" @click="queryPackages">查询</el-button>
       <el-button icon="Plus" color="green" @click="beforeAddPackage">上架</el-button>
     </header>
     <div class="layout_main layout_el-table">
       <el-table :data="packageList" stripe>
-        <el-table-column prop="name" label="套餐名称" />
-        <el-table-column prop="price" label="套餐价格" />
-        <el-table-column prop="description" label="套餐描述" />
-        <el-table-column prop="createTime" label="创建时间" />
-        <el-table-column prop="createStaffName" label="创建人" />
+        <el-table-column prop="name" label="套餐名称"/>
+        <el-table-column prop="originPrice" label="套餐原价"/>
+        <el-table-column prop="discountPrice" label="套餐优惠价"/>
+        <el-table-column prop="description" label="套餐描述"/>
+        <el-table-column prop="createTime" label="创建时间"/>
+        <el-table-column prop="createStaffName" label="创建人"/>
         <el-table-column label="状态">
           <template #default="{row}">
             <el-switch
@@ -94,8 +95,10 @@
               :auto-upload="false"
               :on-success="onSubmitSuccess"
           >
-            <el-image v-if="imageUrl" fit="cover" :src="imageUrl" class="avatar-image" />
-            <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
+            <el-image v-if="imageUrl" fit="cover" :src="imageUrl" class="avatar-image"/>
+            <el-icon v-else class="avatar-uploader-icon">
+              <Plus/>
+            </el-icon>
             <template #tip>
               <div class="gray-text">
                 请选择小于 200Kb 的 jpg/png 格式的图片。
@@ -119,33 +122,57 @@
         <el-form-item label="名称" required>
           <el-input v-model="item.hisName" readonly @click="displaySearchPanel(index)"/>
         </el-form-item>
-        <el-form-item label="单价" required>
-          <el-input v-model="item.price" type="number" class="w-80" />
+        <el-form-item label="原价">
+          <el-input disabled v-model="item.originPrice" type="number" class="w-60"/>
+        </el-form-item>
+        <el-form-item label="优惠价" required>
+          <el-input v-model="item.discountPrice" type="number" class="w-60"/>
         </el-form-item>
         <el-form-item label="数量" required>
-          <el-input v-model.number="item.quantity" class="w-80" />
+          <el-input v-model.number="item.quantity" class="w-60"/>
         </el-form-item>
         <el-form-item v-if="!disableEdit">
           <el-button
               v-if="index === packageItemList.length - 1"
               icon="Plus"
               type="success"
+              title="添加条目"
               @click="addNewItemLine(index)"
           >
-            添加
           </el-button>
           <el-button
+              :disabled="packageItemList.length === 1"
               icon="Minus"
               type="danger"
+              title="删除本条"
               @click="deleteItemLine(index)"
           >
-            删除
           </el-button>
         </el-form-item>
+        <div style="margin: -16px 0 12px 20px;">
+          <el-tag v-if="item.genderRestriction" type="warning" style="margin-right: 8px">
+            限 {{item.genderRestriction === 1 ? '男' : '女'}}性
+          </el-tag>
+          <el-tag v-if="item.minAgeRestriction" style="margin-right: 8px">
+            最小 {{item.minAgeRestriction}}岁
+          </el-tag>
+          <el-tag v-if="item.maxAgeRestriction" style="margin-right: 8px">
+            最大 {{item.maxAgeRestriction}}岁
+          </el-tag>
+          <el-tag v-if="item.genderConflict" type="danger" style="margin-right: 8px">
+            限定性别与其他项目冲突
+          </el-tag>
+          <el-tag v-if="item.ageConflict" type="danger">
+            年龄限制与其他项目冲突
+          </el-tag>
+        </div>
       </el-form>
 
       <template #footer>
-        <div style="flex: auto" v-if="!disableEdit">
+        <div v-if="disableEdit">
+          <el-button @click="mode = 'edit'" type="primary" size="default">编辑</el-button>
+        </div>
+        <div style="flex: auto" v-else>
           <el-button @click="showCreation = false" size="default">取消</el-button>
           <el-button @click="submitUpload" size="default" type="primary">提交</el-button>
         </div>
@@ -154,8 +181,10 @@
     <Search
         v-if="showSearch"
         med-type="01"
-        target="SFXM"
+        target="JY"
         title="收费项目查询"
+        width="520px"
+        show-mall-type
         @close="showSearch = false"
         @click-item="handleClickSearchItem"
     />
@@ -165,6 +194,7 @@
 <script setup>
 import {
   getPackagesByCondition,
+  getOriginPrice,
   getPackageDetail,
   createNewPackage2,
   updatePackageState
@@ -189,6 +219,7 @@ const inquiry = reactive({
 })
 
 const packageList = ref([])
+
 function queryPackages() {
   inquiry.start = dateRange.value.start
   inquiry.end = dateRange.value.end
@@ -204,8 +235,8 @@ function changePackageState(row) {
 }
 
 const packageMainRules = reactive({
-  name: [ { required: true, message: '请输入套餐名称', trigger: 'blur' } ],
-  description: [ { required: true, message: '请输入套餐描述', trigger: 'blur' } ],
+  name: [{required: true, message: '请输入套餐名称', trigger: 'blur'}],
+  description: [{required: true, message: '请输入套餐描述', trigger: 'blur'}],
 })
 
 const mode = ref('see')
@@ -226,10 +257,12 @@ const mainPackage = ref({})
 const uploadRef = ref()
 const fileList = ref([])
 const imageUrl = ref('');
+
 function beforeAddPackage() {
   mode.value = 'add';
   showCreation.value = true
 }
+
 function handleSelectImage({raw}) {
   if (raw.type !== "image/jpeg" && raw.type !== "image/png") {
     ElMessage.error("请选择 jpg/png 格式的图片!");
@@ -243,6 +276,7 @@ function handleSelectImage({raw}) {
   }
   imageUrl.value = URL.createObjectURL(raw);
 }
+
 function handleExceed(files) {
   uploadRef.value.clearFiles();
   const file = files[0];
@@ -253,15 +287,70 @@ function handleExceed(files) {
 const packageItemList = ref([{quantity: 1}])
 const showSearch = ref(false)
 const currentIndex = ref(0)
+
 function displaySearchPanel(index) {
   currentIndex.value = index
   showSearch.value = true
 }
-function handleClickSearchItem(val) {
-  packageItemList.value[currentIndex.value].hisCode = val.code
-  packageItemList.value[currentIndex.value].hisName = val.name
-  showSearch.value = false
+
+async function handleClickSearchItem(val) {
+  const targetItem = packageItemList.value[currentIndex.value]
+  targetItem.hisCode = val.code
+  targetItem.hisName = val.name
+  targetItem.type = val.type
+  if (val.type === 'ZL') {
+    targetItem.originPrice = val.price
+    targetItem.discountPrice = val.price
+  } else {
+    targetItem.genderRestriction = val.genderRestriction
+    targetItem.minAgeRestriction = val.minAgeRestriction
+    targetItem.maxAgeRestriction = val.maxAgeRestriction
+    await getOriginPrice(val.type, val.code).then(price => {
+      targetItem.originPrice = price
+      targetItem.discountPrice = price
+    })
+  }
+  showSearch.value = false;
+  checkConflict()
 }
+
+function checkConflict() {
+  let maleRestriction = false
+  let femaleRestriction = false
+  let minAgeRestriction = -1
+  let maxAgeRestriction = 1000
+  packageItemList.value.forEach(item => {
+    if (item.genderRestriction === 1) {
+      maleRestriction = true
+    } else if (item.genderRestriction === 2) {
+      femaleRestriction = true
+    }
+    if (item.minAgeRestriction && item.minAgeRestriction > minAgeRestriction) {
+      minAgeRestriction = item.minAgeRestriction
+    }
+    if (item.maxAgeRestriction && item.maxAgeRestriction < maxAgeRestriction) {
+      maxAgeRestriction = item.maxAgeRestriction
+    }
+  })
+  packageItemList.value.forEach(item => {
+    if (maleRestriction && femaleRestriction) {
+      if (item.genderRestriction) {
+        item.genderConflict = true
+      }
+    } else {
+      item.genderConflict = false
+    }
+    if (minAgeRestriction > maxAgeRestriction) {
+      if (item.minAgeRestriction || item.maxAgeRestriction) {
+        item.ageConflict = true
+      }
+    } else {
+      item.ageConflict = false
+    }
+  })
+
+}
+
 function addNewItemLine(index) {
   let item = packageItemList.value[index]
   if (!isValidItem(item)) {
@@ -269,8 +358,10 @@ function addNewItemLine(index) {
   }
   packageItemList.value.push({quantity: 1});
 }
+
 function deleteItemLine(index) {
   packageItemList.value.splice(index, 1);
+  checkConflict()
 }
 
 function isValidItem(item) {
@@ -278,8 +369,10 @@ function isValidItem(item) {
     ElMessage.error('请先填写项目名称')
     return false
   }
-  if (!item.price || item.price < 0) {
-    ElMessage.error('项目单价不能小于 0')
+  if (item.discountPrice === null
+      || item.discountPrice === undefined
+      || item.discountPrice === '') {
+    ElMessage.error('项目优惠价不能为空')
     return false
   }
   if (!item.quantity || item.quantity < 1) {
@@ -288,6 +381,7 @@ function isValidItem(item) {
   }
   return true;
 }
+
 const addedItemCode = ref([])
 
 const header = {
@@ -297,6 +391,7 @@ const creation = ref({
   mainPackageJson: null,
   packageItemListJson: null
 })
+
 function submitUpload() {
   addedItemCode.value = []
   if (!mainPackage.value.name) {
@@ -317,6 +412,10 @@ function submitUpload() {
   }
   for (let i = 0; i < packageItemList.value.length; i++) {
     let item = packageItemList.value[i]
+    if (item.genderConflict || item.ageConflict) {
+      ElMessage.error('请先解决冲突项')
+      return
+    }
     if (addedItemCode.value.indexOf(item.hisCode) !== -1) {
       ElMessage.error('请勿添加重复项')
       return
@@ -389,9 +488,15 @@ function beforeEditPackage(id) {
   .ml-12 {
     margin-left: 12px;
   }
+
   .w-80 {
     width: 80px;
   }
+
+  .w-60 {
+    width: 60px;
+  }
+
   .gray-text {
     color: gray;
   }
@@ -405,9 +510,11 @@ function beforeEditPackage(id) {
       overflow: hidden;
       transition: var(--el-transition-duration-fast);
     }
+
     .el-upload:hover {
       border-color: var(--el-color-primary);
     }
+
     .avatar-uploader-icon {
       font-size: 28px;
       color: #8c939d;
@@ -415,11 +522,16 @@ function beforeEditPackage(id) {
       height: 100px;
       text-align: center;
     }
+
     .avatar-image {
       width: 100px;
       height: 100px;
     }
   }
+
+  .el-form--inline .el-form-item {
+    margin-right: 16px;
+  }
 }
 
 </style>