huangxw 10 місяців тому
батько
коміт
21133e9982

+ 1 - 0
package.json

@@ -39,6 +39,7 @@
     "js-cookie": "3.0.5",
     "jsencrypt": "3.3.2",
     "nprogress": "0.2.0",
+    "number-precision": "^1.6.0",
     "pinia": "2.2.6",
     "screenfull": "6.0.2",
     "vue": "3.5.13",

+ 2 - 1
src/views/cdt/discount/index.vue

@@ -10,7 +10,7 @@
                     <vxe-column type="seq" width="60" title="序号" align="center" />
                     <vxe-column title="会员级别" align="center" field="name" min-width="100" :formatter="colNoData" />
                     <vxe-column title="折扣标准" align="center" min-width="100">
-                        <template #default="{ row }">{{ row?.discount }}折</template>
+                        <template #default="{ row }">{{ NP.times(row?.discount, 10) }}折</template>
                     </vxe-column>
                     <vxe-column title="创建人" align="center" field="createByName" min-width="100" :formatter="colNoData" />
                     <vxe-column title="创建时间" align="center" field="createTime" min-width="100" :formatter="colNoData" />
@@ -24,6 +24,7 @@
 <script setup name="Discount" lang="ts">
 import { vipDiscountList } from '@/api/cdt/discount';
 import { colNoData } from '@/utils/noData';
+import NP from 'number-precision';
 const queryParams = ref<any>({
     pageNum: 1,
     pageSize: 10,

+ 183 - 25
src/views/cdt/menus/form/index.vue

@@ -11,13 +11,43 @@
                 </el-button>
             </div>
             <div class="flex1 over-auto">
-                <el-form :model="form" :rules="rules" ref="formRef" label-width="auto" label-position="top">
+                <el-form ref="formRef" label-width="auto" label-position="top" :model="form" :rules="rules">
                     <div class="pd-16 border-bottom">
                         <el-form-item>
-                            <div class="flex1"><add-btn content="选择检测项目"></add-btn></div>
+                            <div class="flex1">
+                                <template v-if="!form.items.length">
+                                    <add-btn @click="showSelectItems = true" content="选择检测项目"></add-btn>
+                                </template>
+                                <template v-else>
+                                    <div class="d-flex">
+                                        <div class="flex1 ov-hd f-s-16 c-333 f-w-5">已选择{{ form.items.length }}项检测项目,合计{{ totalCountPrice }}元</div>
+                                        <div>
+                                            <el-button @click="addItems" type="primary" text>
+                                                <el-icon><Plus /></el-icon>
+                                                继续添加
+                                            </el-button>
+                                            <el-button @click="clearItemsAdd" type="danger" text>
+                                                <el-icon><DeleteFilled /></el-icon>
+                                                清空重选
+                                            </el-button>
+                                        </div>
+                                    </div>
+                                    <vxe-table ref="tableRightRef" border :data="form.items" :column-config="{ resizable: true }">
+                                        <vxe-column type="seq" width="60" title="序号" align="center" />
+                                        <vxe-column title="检测项目" align="center" field="name" min-width="100" :formatter="colNoData" />
+                                        <vxe-column title="单价(元、批次)" align="center" field="price" min-width="100" :formatter="colNoData" />
+                                        <vxe-column title="备注" align="center" field="description" min-width="100" :formatter="colNoData" />
+                                        <vxe-column title="操作" align="center">
+                                            <template #default="{ $rowIndex }">
+                                                <el-button type="danger" @click="deleteRow($rowIndex)" text>删除</el-button>
+                                            </template>
+                                        </vxe-column>
+                                    </vxe-table>
+                                </template>
+                            </div>
                         </el-form-item>
                     </div>
-                    <div class="pd-16 border-bottom">
+                    <div class="pd-16 border-bottom ov-hd">
                         <div class="info-title mb-10">套餐基本信息</div>
                         <el-row :gutter="90">
                             <el-col :span="8">
@@ -34,23 +64,27 @@
                             </el-col>
                             <el-col :span="8">
                                 <el-form-item label="制定规则" prop="permitType">
-                                    <el-radio-group v-model="form.permitType">
+                                    <el-radio-group v-model="form.permitType" @change="changePermitType">
                                         <el-radio v-for="item in dm_permit_type" :key="item.value" :label="item.value">{{ item.label }}</el-radio>
                                     </el-radio-group>
                                 </el-form-item>
                             </el-col>
-                            <el-col :span="8">
-                                <el-form-item label="适用类型" prop="permit">
-                                    <el-select v-model="form.permit" clearable multiple placeholder="请选择适用类型">
-                                        <el-option v-for="item in vip_level" :key="item.value" :label="item.label" :value="item.value"></el-option>
-                                    </el-select>
-                                </el-form-item>
-                            </el-col>
-                            <el-col :span="8">
-                                <el-form-item label="适用企业" prop="permit">
-                                    <SearchSelect></SearchSelect>
-                                </el-form-item>
-                            </el-col>
+                            <template v-if="form.permitType === '1'">
+                                <el-col :span="8">
+                                    <el-form-item label="适用类型" prop="permit">
+                                        <el-select v-model="form.permit" @change="changePermit" clearable multiple placeholder="请选择适用类型">
+                                            <el-option v-for="item in vip_level" :key="item.value" :label="item.label" :value="item.value"></el-option>
+                                        </el-select>
+                                    </el-form-item>
+                                </el-col>
+                            </template>
+                            <template v-if="form.permitType === '2'">
+                                <el-col :span="8">
+                                    <el-form-item label="适用企业" prop="permitCpy">
+                                        <SearchSelect v-model="form.permitCpy"></SearchSelect>
+                                    </el-form-item>
+                                </el-col>
+                            </template>
                             <el-col :span="8">
                                 <el-form-item label="检测周期" prop="period">
                                     <el-input v-model.number="form.period" clearable placeholder="请输入检测周期">
@@ -60,7 +94,7 @@
                             </el-col>
                             <el-col :span="8">
                                 <el-form-item label="上架数量" prop="totalCount">
-                                    <el-input v-model.number="form.totalCount" clearable placeholder="请输入套餐价格"></el-input>
+                                    <el-input v-model.number="form.totalCount" clearable placeholder="请输入上架数量"></el-input>
                                 </el-form-item>
                             </el-col>
                             <el-col :span="8">
@@ -69,8 +103,8 @@
                                 </el-form-item>
                             </el-col>
                             <el-col :span="8">
-                                <el-form-item label="送样信息" prop="price">
-                                    <el-input type="textarea" placeholder="请输入送样信息" :rows="4" show-word-limit maxlength="100"></el-input>
+                                <el-form-item label="送样信息" prop="description">
+                                    <el-input type="textarea" v-model="form.description" placeholder="请输入送样信息" :rows="4" show-word-limit maxlength="100"></el-input>
                                 </el-form-item>
                             </el-col>
                             <el-col :span="8">
@@ -90,30 +124,154 @@
                             </el-col>
                         </el-row>
                     </div>
-                    <div class="pd-16">
-                        <div class="info-title">套餐价格确认</div>
+                    <div v-if="form.permit" class="pd-16">
+                        <div class="info-title mb-10">套餐价格确认</div>
+                        <vxe-table ref="tableRightRef" border :data="form.priceDetail" :column-config="{ resizable: true }">
+                            <vxe-column type="seq" width="60" title="序号" align="center" />
+                            <vxe-column v-if="form.permitType === '2'" title="企业名称" align="center" field="name" min-width="100" :formatter="colNoData" />
+                            <vxe-column title="适用类型" align="center" field="name" min-width="100" :formatter="colNoData" />
+                            <vxe-column title="折扣标准" align="center" min-width="100">
+                                <template #default="{ row }">{{ NP.times(row?.discount, 10) }}折</template>
+                            </vxe-column>
+                            <vxe-column title="折扣后售价" align="center" field="name" min-width="100">
+                                <template #default="{ row }">{{ row?.discountPrice }}元</template>
+                            </vxe-column>
+                            <vxe-column title="最终售价" align="center" min-width="100">
+                                <template #default="{ row }">
+                                    <el-input v-model="row.price" clearable placeholder="请输入最终售价">
+                                        <template #suffix>元</template>
+                                    </el-input>
+                                </template>
+                            </vxe-column>
+                        </vxe-table>
                     </div>
                 </el-form>
             </div>
+            <div class="d-flex a-c j-c pd-16">
+                <el-button @click="router.go(-1)">取消</el-button>
+                <el-button @click="save" color="#0079fe">暂存</el-button>
+                <el-button @click="save" type="primary">提交</el-button>
+                <el-button @click="submitForm" type="warning">立即上架</el-button>
+            </div>
         </div>
     </div>
-    <TransferItems v-if="showSelectItems" v-model:show="showSelectItems"></TransferItems>
+    <TransferItems ref="TransferItemsRef" v-model:show="showSelectItems" @change="changeItems"></TransferItems>
 </template>
 
 <script setup name="Member-detail" lang="ts">
 import { AddBtn, SearchSelect } from '@/views/models';
 import { TransferItems } from '../../models';
+import NP from 'number-precision';
+import { colNoData } from '@/utils/noData';
+import { vipDiscountList } from '@/api/cdt/discount';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const { dm_package_type, dm_permit_type, vip_level } = toRefs<any>(proxy?.useDict('dm_package_type', 'dm_permit_type', 'vip_level'));
 // 字典
+const TransferItemsRef = ref<any>();
 const router = useRouter();
-const showSelectItems = ref(true);
+const showSelectItems = ref(false);
 const form = ref<any>({
-   items: []
+   items: [],
+   priceDetail: []
 });
 const rules = reactive({
     items: [
-        { required: true, message: '请选择检测项目', trigger: 'change' }
+        { required: true, message: '请选择检测项目', trigger: 'change' },
+    ],
+    name: [
+        { required: true, message: '请输入套餐名称', trigger: 'blur' }
+    ],
+    publicFlag: [
+        { required: true, message: '请选择套餐类型', trigger: 'change' }
+    ],
+    permitType: [
+        { required: true, message: '请选择制定规则', trigger: 'change' }
+    ],
+    permit: [
+        { required: true, message: '请选择适用类型', trigger: 'change' }
+    ],
+    permitCpy: [
+        { required: true, message: '请选择适用企业', trigger: 'change' }
+    ],
+    period: [
+        { required: true, message: '请输入检测周期', trigger: 'blur' }
+    ],
+    totalCount: [
+        { required: true, message: '请输入上架数量', trigger: 'blur' }
+    ],
+    standard: [
+        { required: true, message: '请输入执行标准', trigger: 'blur' }
+    ],
+    description: [
+        { required: true, message: '请输入送样信息', trigger: 'blur' }
+    ],
+    purchaseNotes: [
+        { required: true, message: '请输入购买须知', trigger: 'blur' }
+    ],
+    coverImg: [
+        { required: true, message: '请上传封面图', trigger: 'blur' }
+    ],
+    proImg: [
+        { required: true, message: '请上传产品图', trigger: 'blur' }
     ]
 });
+const save = () => {
+    console.log('暂存');
+};
+const submitForm = () => {
+    console.log('立即上架');
+};
+// 合计价格
+const totalCountPrice = computed(() => {
+    return form.value.items.reduce((total: number, item: any) => {
+        return NP.plus(total, item.price);
+    }, 0);
+});
+const changeItems = (val: any) => {
+    form.value.items = val;
+    changePermitType();
+};
+// 继续添加方法
+const addItems = () => {
+    // 保留之前选中
+    TransferItemsRef.value?.setSelectItems(form.value.items);
+    showSelectItems.value = true;
+};
+// 清空重选方法
+const clearItemsAdd = () => {
+    form.value.items = [];
+    TransferItemsRef.value?.clearAll();
+    showSelectItems.value = true;
+};
+// 删除行
+const deleteRow = (index: number) => {
+    form.value.items.splice(index, 1);
+};
+const discounts = ref<any>([]);
+const getDiscount = async () => {
+    // 获取折扣
+    const res = await vipDiscountList({ pageSize: 1000, pageNum: 1 });
+    if (!res || res.code !== 200) return;
+    discounts.value = res.rows;
+};
+const changePermit = (val: string[]) => {
+    console.log(val);
+    form.value.priceDetail = discounts.value.filter(({ level }) => val.includes(level + '')).map(item => {
+        return {
+            ...item,
+            memberLevel: item.level,
+            originalPrice: totalCountPrice.value,
+            discountPrice: NP.times(item.discount, totalCountPrice.value),
+            price: NP.times(item.discount, totalCountPrice.value) || undefined
+        };
+    });
+};
+const changePermitType = () => {
+    form.value.permit = [];
+    form.value.permitCpy = '';
+    form.value.priceDetail = [];
+};
+onMounted(() => {
+    getDiscount();
+});
 </script>

+ 25 - 2
src/views/cdt/models/transferItems.vue

@@ -92,7 +92,7 @@ import { FormInstance } from 'element-plus';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 const dialogVisible = ref(false);
-const emit = defineEmits(['update:show', 'close', 'success']);
+const emit = defineEmits(['update:show', 'close', 'change']);
 const props = defineProps({
     show: propTypes.bool.def(false),
     title: propTypes.string.def('选择检测项目'),
@@ -172,7 +172,15 @@ const close = () => {
 };
 const submitForm = async () => {
     try {
-    } catch (error) { }
+        if (!targetList.value.length) {
+            // 抛出错误
+            return proxy.$modal.msgWarning('请选择检测项目');
+        }
+        emit('change', targetList.value);
+        close();
+    } catch (error) {
+        proxy.$modal.msgWarning(error);
+    }
 };
 const tableLeftRef = ref<any>();
 const tableRightRef = ref<any>();
@@ -184,6 +192,17 @@ const transferLeft = () => {
     tableLeftRef.value?.setCheckboxRow(tableRightRef.value?.getCheckboxRecords(), false);
     tableRightRef.value.setCheckboxRow(tableRightRef.value?.getCheckboxRecords(), false);
 };
+// 清空全部已选
+const clearAll = () => {
+    tableLeftRef.value?.clearCheckboxRow();
+    tableRightRef.value?.clearCheckboxRow();
+    targetList.value = [];
+};
+// 设置已选
+const setSelectItems = (val: any) => {
+    targetList.value = val;
+    tableLeftRef.value?.setCheckboxRow(val, true);
+};
 watch(
     () => props.show,
     (val) => {
@@ -195,6 +214,10 @@ watch(
     },
     { immediate: true }
 );
+defineExpose({
+    clearAll,
+    setSelectItems
+});
 </script>
 <style lang="scss" scoped>
 .tree-wrap {

+ 11 - 4
src/views/models/SearchSelect.vue

@@ -1,5 +1,5 @@
 <template>
-    <el-select ref="selectDropRef" v-selectLazyLoad:pageNum="loadMoreData" v-model="value" filterable popper-class="custom-dropdown" remote reserve-keyword :remote-method="remoteMethod" remote-show-suffix clearable placeholder="请选择适用企业">
+    <el-select ref="selectDropRef" @change="changeSelect" v-model="value" filterable popper-class="custom-dropdown" remote reserve-keyword :remote-method="remoteMethod" remote-show-suffix clearable placeholder="请选择适用企业">
         <div class="optionBox" infinite-scroll-delay="500" infinite-scroll-distance="20" v-infinite-scroll="load">
             <el-option v-for="item in options" :key="item.value" filterable :label="item.cpyName" :value="item.id"></el-option>
         </div>
@@ -9,6 +9,13 @@
 import { getEnterpriseList } from '@/api/cdt/menus'
 // 防抖
 import { debounce } from 'lodash';
+const props = defineProps({
+    modelValue: {
+        type: String,
+        default: ''
+    }
+})
+const emit = defineEmits(['change', 'update:modelValue'])
 const value = ref('')
 const options = ref([])
 const total = ref(0)
@@ -32,7 +39,6 @@ const getList = async (hasRx = true) => {
     }
 }
 const remoteMethod = (text: string) => {
-    console.log(text);
     if (text) {
         queryParams.value.cpyName = text
         selectSearch()
@@ -44,8 +50,9 @@ const load = () => {
         getList(false)
     }
 }
-const loadMoreData = (event: any) => {
-    console.log('---');
+const changeSelect = (val: string) => {
+    emit('update:modelValue', val)
+    emit('change', val)
 }
 const selectSearch = debounce(() => {
     getList()

+ 2 - 2
vite.config.ts

@@ -26,8 +26,8 @@ export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => {
             proxy: {
                 [env.VITE_APP_BASE_API]: {
                     // target: 'http://dm.yujin.shuziyunyao.com/api',
-                    target: 'http://dm.yujin.shuziyunyao.com/api',
-                    // target: 'http://192.168.1.68:8080',
+                    // target: 'http://dm.yujin.shuziyunyao.com/api',
+                    target: 'http://192.168.1.68:8080',
                     changeOrigin: true,
                     ws: true,
                     rewrite: (path) => path.replace(new RegExp('^' + env.VITE_APP_BASE_API), '')