Ver Fonte

Merge branch 'master' of http://git.yujin.shuziyunyao.com/yujin/digital-medicine-front

longmh há 10 meses atrás
pai
commit
b381450fe7

+ 1 - 0
package.json

@@ -46,6 +46,7 @@
     "vue-cropper": "1.1.1",
     "vue-i18n": "10.0.5",
     "vue-json-pretty": "2.4.0",
+    "vue-qr": "^4.0.9",
     "vue-router": "4.4.5",
     "vue-types": "5.1.3",
     "vxe-table": "4.6.17"

+ 64 - 0
src/api/price/report/index.ts

@@ -0,0 +1,64 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+
+/**
+ * 查询产地价格发布记录详情列表
+ * @param query
+ * @returns {*}
+ */
+
+export const originPriceDetail = (query?: any): any => {
+    return request({
+        url: '/dgtmedicine/originPriceDetail/list',
+        method: 'get',
+        params: query
+    });
+};
+/**
+ * 查询产地品种列表
+ * @param query
+ * @returns {*}
+ */
+
+export const originPriceList = (query?: any): any => {
+    return request({
+        url: '/dgtmedicine/originPrice/list',
+        method: 'get',
+        params: query
+    });
+};
+/**
+ * 获取产地价格发布记录详细信息
+ * @param query
+ * @returns {*}
+ */
+export const originPriceDetailInfo = (id?: any): any => {
+    return request({
+        url: `/dgtmedicine/originPrice/getInfo/${id}`,
+        method: 'get'
+    });
+};
+/**
+ * 场地价格审核统计
+ * @param query
+ * @returns {*}
+ */
+export const priceDetailCount = (query?: any): any => {
+    return request({
+        url: '/dgtmedicine/originPriceDetail/priceDetailCount',
+        method: 'get',
+        params: query
+    });
+};
+/**
+ * 价格审批
+ * @param query
+ * @returns {*}
+ */
+export const approvalPrice = (query?: any): any => {
+    return request({
+        url: '/dgtmedicine/originPriceDetail/approvalPrice',
+        method: 'post',
+        data: query
+    });
+};

+ 89 - 0
src/api/price/station/index.ts

@@ -0,0 +1,89 @@
+import request from '@/utils/request';
+import { AxiosPromise } from 'axios';
+
+/**
+ * 查询产地监测点列表
+ * @param query
+ * @returns {*}
+ */
+
+export const originCpyList = (query?: any): any => {
+    return request({
+        url: '/dgtmedicine/originCpy/list',
+        method: 'get',
+        params: query
+    });
+};
+/**
+ * 检测点统计
+ * @param query
+ * @returns {*}
+ */
+export const queryOriginCpyCount = (query?: any): any => {
+    return request({
+        url: '/dgtmedicine/originCpy/queryOriginCpyCount',
+        method: 'get',
+        params: query
+    });
+};
+/**
+ * 添加监测点企业信息
+ * @param query
+ * @returns {*}
+ */
+export const listByPage = (query?: any): any => {
+    return request({
+        url: 'dgtmedicine/originCpy/chooseOriginCpy',
+        method: 'get',
+        params: query
+    });
+};
+/**
+ * 添加监测点
+ * @param query
+ * @returns {*}
+ */
+export const addOriginCpy = (query?: any): any => {
+    return request({
+        url: '/dgtmedicine/originCpy/addOriginCpy',
+        method: 'post',
+        data: query
+    });
+};
+
+/**
+ * 批量删除检测点
+ * @param query
+ * @returns {*}
+ */
+export const deleteOriginCpy = (query?: any): any => {
+    return request({
+        url: '/dgtmedicine/originCpy/delOriginCpy',
+        method: 'post',
+        data: query
+    });
+};
+/**
+ * 批量修改检测点有效期
+ * @param query
+ * @returns {*}
+ */
+export const updateOriginCpy = (query?: any): any => {
+    return request({
+        url: '/dgtmedicine/originCpy/editValidDate',
+        method: 'post',
+        data: query
+    });
+};
+
+/**
+ * 获取产地检测点详细信息
+ * @param query
+ * @returns {*}
+ */
+export const originCpyInfo = (id?: any): any => {
+    return request({
+        url: `/dgtmedicine/originCpy/getInfo/${id}`,
+        method: 'get'
+    });
+};

+ 11 - 6
src/components/FileUpload/index.vue

@@ -63,7 +63,6 @@ const props = defineProps({
   isShowTip: propTypes.bool.def(true),
   tipText: propTypes.string.def(''),
   span: propTypes.number.def(24),
-  isObject: propTypes.bool.def(false),
   multiple: propTypes.bool.def(true),
   white: propTypes.bool.def(false),
   // 上传数据格式
@@ -89,15 +88,21 @@ const fileUploadRef = ref<ElUploadInstance>();
 const progressList = ref<any>([]);
 watch(
   () => props.modelValue,
-  async (val) => {
+  async (val: any) => {
       if (val) {
           let temp = 1;
           // 首先将值转为数组
           let list = [];
            if (props.format === 'array' && Array.isArray(val)) {
               list = val;
-           } else if (props.format === 'object' || props.isObject) {
-              list = [val];
+           } else if (props.format === 'object') {
+              list = [{
+                    name: val.fileName,
+                    url: val.url,
+                    fileSize: val.fileSize,
+                    fileType: val.fileType,
+                    ossId: val.ossId
+              }];
           } else {
               const res = await listByIds(val as string);
               list = res.data.map((oss) => {
@@ -187,7 +192,7 @@ const uploadedSuccessfully = () => {
       if (props.format === 'id') {
          emit('change', listToString(valuef));
          emit('update:modelValue', listToString(valuef));
-      } else if (props.isObject || props.format === 'object') {
+      } else if (props.format === 'object') {
           emit('change', valuef[0])
           emit('update:modelValue', valuef[0]);
       } else {
@@ -205,7 +210,7 @@ const handleDelete = (index: number) => {
   fileUploadRef.value?.abort(fileList.value[index]);
   fileList.value.splice(index, 1);
   const valuef = fileList.value.map(({ name, url, fileType, fileSize }) => ({ fileName: name, url, fileSize, fileType }));
-  if (props.isObject) {
+  if (props.format === 'object') {
       emit('change', null)
       emit('update:modelValue', null);
   } else {

+ 4 - 3
src/views/cdt/items/index.vue

@@ -3,12 +3,12 @@
         <div class="bg-fff flex1 ov-hd d-flex flex-cln">
             <div class="pd-16 border-bottom">
                 <div class="f-s-20 c-333 f-w-7 mb-20">检测项查询</div>
-                <searchTabs v-model="tabActive" :list="[ { label: '按检测项目', value: '1' }, { label: '按执行标准', value: '2' } ]" :is-num="false"></searchTabs>
+                <searchTabs v-model="tabActive" :list="[{ label: '按检测项目', value: '1' }, { label: '按执行标准', value: '2' }]" :is-num="false"></searchTabs>
             </div>
             <div class="pd-16">
                 <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="auto">
                     <el-form-item label="检测项名称:" prop="name">
-                        <el-input v-model="queryParams.name" placeholder="请输入检测项名称关键字" clearable style="width: 180px" @keyup.enter="handleQuery" />
+                        <el-input v-model="queryParams.name" placeholder="请输入检测项名称关键字" clearable style="width: 180px" />
                     </el-form-item>
                     <el-form-item>
                         <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
@@ -98,7 +98,7 @@ const resetQuery = () => {
     };
     // 重置树高亮
     treeItemsRef.value?.setCurrentKey(null, true);
-    treeStandardsRef.value?.setCurrentKey(null, true);
+    treeStandardsRef.value?.setCurrentKey(null, false);
     handleQuery()
 };
 const getTabsTree = async () => {
@@ -140,6 +140,7 @@ onMounted(() => {
     border-right: 1px solid #ebeef5;
     padding: 16px;
 }
+
 .content-border {
     border: 1px solid var(--border-color);
 }

+ 1 - 1
src/views/cdt/menus/detail/index.vue

@@ -32,7 +32,7 @@
                             <el-image style="width: 100px; height: 100px" :src="form?.coverImg" :zoom-rate="1.2" :max-scale="7" :min-scale="0.2" :preview-src-list="[form?.coverImg]" fit="cover"></el-image>
                         </el-descriptions-item>
                         <el-descriptions-item label="产品图:">
-                            <template v-for="(item, index) in form?.proImg.split(',')" :key="index">
+                            <template v-for="(item, index) in form?.proImg?.split(',')" :key="index">
                                 <el-image style="width: 100px; height: 100px;margin-right: 12px;" :src="item" fit="cover" :zoom-rate="1.2" :max-scale="7" :min-scale="0.2" :initial-index="index" :preview-src-list="[item]"></el-image>
                             </template>
                         </el-descriptions-item>

+ 56 - 3
src/views/cdt/menus/index.vue

@@ -45,7 +45,7 @@
                         <vxe-column title="套餐名称" fixed="left" align="center" field="name" min-width="100" :formatter="colNoData" />
                         <vxe-column title="适用对象" field="applyType" min-width="100">
                             <template #default="{ row }">
-                                <view class="d-flex flex-cln">
+                                <view class="d-flex flex-cln" v-if="row?.permitType == '1'">
                                     <template v-for="(item, index) in row?.priceDetail" :key="index">
                                         <view>
                                             {{ item?.memberLevelName }}-{{ NP.times(item?.memberDiscount, 10) }}折
@@ -53,6 +53,14 @@
                                         </view>
                                     </template>
                                 </view>
+                                <view class="d-flex flex-cln" v-if="row?.permitType == '2'">
+                                    <view>
+                                        {{ row?.permitCpyNames?.join(',') }}-{{
+                                            NP.times(row?.priceDetail[0]?.memberDiscount, 10)
+                                        }}折
+                                        <span class="c-333 f-w-5">({{ row?.priceDetail[0]?.price }})</span>
+                                    </view>
+                                </view>
                             </template>
                         </vxe-column>
                         <vxe-column title="检测项目" min-width="140">
@@ -69,6 +77,22 @@
                         </vxe-column>
                         <vxe-column title="上架数量" field="totalCount" width="80" :formatter="colNoData"></vxe-column>
                         <vxe-column title="销量" field="orderedCount" width="80" :formatter="colNoData"></vxe-column>
+                        <vxe-column title="开始时间" field="validFrom" width="160">
+                            <template #default="{ row }">{{ row?.validFrom }}</template>
+                        </vxe-column>
+                        <vxe-column title="结束时间" field="validUntil" width="160">
+                            <template #default="{ row }">{{ row?.validUntil }}</template>
+                        </vxe-column>
+                        <vxe-column title="剩余时间" field="restDay" width="100">
+                            <template #default="{ row }">
+                                <span v-if="row.status == 0">未上架</span>
+                                <span v-if="row.status == 2"></span>
+                                <span v-if="row.status == 1 && new Date(row?.validUntil ) > new Date()">{{Math.floor((new Date(row?.validUntil).getTime()-new Date().getTime())/(3600*24*1000))+1 }}天</span>
+                                <span v-else>已过期</span>
+                            </template>
+                        </vxe-column>
+                        <vxe-column title="创建人" field="createName" width="100"></vxe-column>
+                        <vxe-column title="创建时间" field="createTime" width="160"></vxe-column>
                         <vxe-column title="套餐状态" align="center" width="90" fixed="right">
                             <template #default="{ row }">
                                 <span v-if="+row?.status === 0" class="c-danger">未上架</span>
@@ -86,7 +110,7 @@
                                 <template v-if="+row?.status === 1">
                                     <el-button @click="soldOut(row)" text type="danger">下架</el-button>
                                     <span></span>
-                                    <el-button text type="primary">分享</el-button>
+                                    <el-button text type="primary" @click="showShareImg(row)">分享</el-button>
                                 </template>
                                 <template v-if="+row?.status === 2">
                                     <el-button @click="putaway(row)" text type="primary">上架</el-button>
@@ -105,9 +129,17 @@
             <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
         </div>
     </div>
+    <el-dialog title="套餐分享" v-model="shareDialog" width="350px">
+        <div class="d-flex flex-cln">
+            {{ sharePkgName }}
+            <el-button type="primary" @click="download">下载</el-button>
+        </div>
+        <vue-qr ref="qrCode" :text="shareText" v-if="shareText" :size="300"></vue-qr>
+    </el-dialog>
     <rowItems v-if="showRowItems" v-model:show="showRowItems" :packageId="rowId"></rowItems>
 </template>
 <script setup name="Menus" lang="ts">
+import vueQr from 'vue-qr/src/packages/vue-qr.vue'
 import { copyTestPackage, testPackageList, testPackageListCount, testPackageSale, testPackageUnSale } from '@/api/cdt/menus';
 import { colNoData } from '@/utils/noData';
 import { searchTabs } from '@/views/models';
@@ -146,7 +178,9 @@ const resetQuery = () => {
 // 获取tabs统计数据
 const tabs = ref<any[]>([]);
 const getTabsCount = debounce(async () => {
-    const res = await testPackageListCount({ ...queryParams.value });
+    const params = { ...queryParams.value }
+    params.publicFlag = ''
+    const res = await testPackageListCount(params);
     if (!res || res.code !== 200) return;
     // this.tabsList = res.rows;
     tabs.value = res.data;
@@ -205,6 +239,25 @@ const queryRowItems = (row: any) => {
     rowId.value = row?.id;
     showRowItems.value = true;
 };
+//二维码分享
+const shareText = ref('');
+const sharePkgName = ref('');
+const shareDialog = ref(false);
+const showShareImg = (row) => {
+    shareText.value = `http://dm.share.yujin.shuziyunyao.com/package?id=${row?.id}`;
+    sharePkgName.value = row?.name;
+    shareDialog.value = true;
+}
+const qrCode = ref<any>(null)
+const download = () => {
+    const a: any = document.createElement('a')
+    // 下载的文件名
+    a.download = `${sharePkgName.value}.png`
+    // url
+    a.href = qrCode.value.$el.src
+    // 触发点击
+    a.click()
+}
 onMounted(() => {
     getTabsCount();
     getList();

+ 6 - 3
src/views/cdt/models/menuInfo.vue

@@ -8,12 +8,15 @@
                 <el-descriptions-item label="制定规则:">{{ selectDictLabel(dm_permit_type,form?.permitType ) }}</el-descriptions-item>
                 <el-descriptions-item v-if="form?.permitType === '1'" label="适用类型:">{{ selectDictLabels(vip_level, form?.permit, ',') || '-' }}</el-descriptions-item>
                 <el-descriptions-item v-if="form?.permitType === '2'" label="适用企业:">{{ form?.permitCpyNames.toString()|| '-' }}</el-descriptions-item>
-                <el-descriptions-item label="检测周期:">{{ form?.period || '-' }}</el-descriptions-item>
+                <el-descriptions-item label="检测周期:">{{ form?.period || '-' }}工作日</el-descriptions-item>
                 <el-descriptions-item label="上架数量:">{{ form?.totalCount || '-' }}</el-descriptions-item>
-                <el-descriptions-item label="执行标准:">{{ form?.standard || '-' }}</el-descriptions-item>
+                <el-descriptions-item></el-descriptions-item>
+                <el-descriptions-item></el-descriptions-item>
+                <el-descriptions-item label="执行标准:" :span="2">{{ form?.standard || '-' }}</el-descriptions-item>
                 <el-descriptions-item label="送样信息:" :span="2">{{ form?.description || '-' }}</el-descriptions-item>
                 <el-descriptions-item label="购买须知:" :span="2">{{ form?.purchaseNotes || '-' }}</el-descriptions-item>
-                <el-descriptions-item label="失效日期:">{{ form?.validUntil || '-' }}</el-descriptions-item>
+                <el-descriptions-item label="创建人:">{{ form?.createName || '-' }}</el-descriptions-item>
+                <el-descriptions-item label="创建时间:">{{ form?.createTime || '-' }}</el-descriptions-item>
             </el-descriptions>
             <el-divider />
             <el-descriptions :column="4" direction="vertical">

+ 1 - 1
src/views/cdt/models/orderInfo.vue

@@ -117,7 +117,7 @@
                         </el-steps>
                         <el-divider />
                     </template>
-                    <template v-if="+info.status >= 2  && +info?.originStatus >= 2">
+                    <template v-if="+info.status >= 2  && +info?.originStatus >= 2 && info?.sendAddress">
                         <div class="f-s-16 c-333 f-w-6 mb-16">寄样信息</div>
                         <div class="d-flex a-c">
                             <div class="card-blcok pd-16 d-flex flex1">

+ 3 - 3
src/views/cdt/models/rowItems.vue

@@ -2,8 +2,8 @@
     <vxe-modal v-model="dialogVisible" :title="title" show-zoom resize show-footer destroy-on-close transfer @hide="close" :width="width">
         <template #default>
             <div class="d-flex flex-cln" style="height: 60vh;">
-                <div class="flex1 ov-hd">
-                    <vxe-table :loading="loading" border :data="list">
+                <div class="flex1 ov-hd" style="height:50vh">
+                    <vxe-table :loading="loading" border :data="list" height="auto">
                         <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" />
@@ -18,7 +18,7 @@
         </template>
     </vxe-modal>
 </template>
-<script setup name="Pay-log" lang="ts">
+<script setup name="rowItems" lang="ts">
 import { getTestPackageItems } from '@/api/cdt/menus';
 import { colNoData } from '@/utils/noData';
 import { propTypes } from '@/utils/propTypes';

+ 1 - 1
src/views/cdt/models/uploadInvoiceForm.vue

@@ -3,7 +3,7 @@
         <template #default>
             <el-form ref="formRef" :model="form" :rules="rules" label-width="auto" hide-required-asterisk>
                 <el-form-item label="发票:" prop="invoice">
-                    <file-upload v-model="form.invoice" :limit="1" isObject :fileType="['pdf']" :span="24" />
+                    <file-upload v-model="form.invoice" :limit="1" format="object" :fileType="['pdf']" :span="24" />
                 </el-form-item>
             </el-form>
         </template>

+ 1 - 1
src/views/cdt/models/uploadReportForm.vue

@@ -3,7 +3,7 @@
         <template #default>
             <el-form ref="formRef" :model="form" :rules="rules" label-width="auto" hide-required-asterisk>
                 <el-form-item label="报告:" prop="report">
-                    <file-upload v-model="form.report" :limit="1" isObject :fileType="['pdf']" :span="24" />
+                    <file-upload v-model="form.report" :limit="1" format="object" :fileType="['pdf']" :span="24" />
                 </el-form-item>
             </el-form>
         </template>

+ 1 - 1
src/views/cdt/orders/detail/index.vue

@@ -21,7 +21,7 @@
                 <div v-show="activeName === '1'" class="flex1 ov-hd d-flex flex-cln">
                     <orderInfo :info="orderItem"></orderInfo>
                 </div>
-                <div v-show="activeName === '2'" class="flex1 ov-hd">
+                <div v-show="activeName === '2'" class="flex1 over-auto">
                     <menuInfo :info="orderItem?.testOrderDetailList[0]"></menuInfo>
                 </div>
             </template>

+ 1 - 1
src/views/dgtmedicine/member/index.vue

@@ -22,7 +22,7 @@
                         <el-select style="width: 140px" v-model="queryParams.vipEnable" clearable placeholder="搜有效期状态">
                             <el-option label="全部" value=""></el-option>
                             <el-option label="有效" value="1"></el-option>
-                            <el-option label="过期" value="-1"></el-option>
+                            <el-option label="过期" value="3"></el-option>
                         </el-select>
                     </el-form-item>
                     <el-form-item>

+ 5 - 2
src/views/dgtmedicine/model/EditVipEndDate.vue

@@ -47,8 +47,11 @@ const close = () => {
 const submitForm = async () => {
     try {
         await formRef.value?.validate();
-        const res = await editValidityDate({ ...form.value, id: props.info?.id });
-        if (res) {
+        proxy?.$modal.loading('修改中...');
+        const res = await editValidityDate({ ...form.value, id: props.info?.id }).finally(() => {
+            proxy?.$modal.closeLoading();
+        });
+        if (res?.code === 200) {
             close();
             emit('success', true);
         }

+ 75 - 0
src/views/price/models/EditStationEndDate.vue

@@ -0,0 +1,75 @@
+<template>
+    <vxe-modal v-model="dialogVisible" :title="title" show-zoom resize show-footer destroy-on-close transfer @hide="close" :width="width" :z-index="100">
+        <template #default>
+            <el-form ref="formRef" :model="form" :rules="rules" label-width="auto">
+                <div class="mb-10 f-s-14 c-333 f-w-5">
+                    修改企业:
+                    <span class="c-primary">{{ mapInfoToNameString(infos) }}</span>
+                </div>
+                <el-form-item label="有效期至:" prop="endDate">
+                    <el-date-picker v-model="form.endDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择有效期" clearable style="width: 100%"></el-date-picker>
+                </el-form-item>
+            </el-form>
+        </template>
+        <template #footer>
+            <el-button @click="close">取消</el-button>
+            <el-button type="primary" @click="submitForm">确认修改</el-button>
+        </template>
+    </vxe-modal>
+</template>
+
+<script setup name="EditStationEndDate" lang="ts">
+import { updateOriginCpy } from '@/api/price/station';
+import { propTypes } from '@/utils/propTypes';
+import { FormInstance } from 'element-plus';
+const emit = defineEmits(['update:show', 'close', 'success']);
+const props = defineProps({
+    show: propTypes.bool.def(false),
+    title: propTypes.string.def('修改监测点有效期'),
+    width: propTypes.number.def(560),
+    infos: propTypes.any.def(null),
+    dict: propTypes.object.def({}),
+});
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const dialogVisible = ref(false);
+const form = ref<any>({
+    endDate: ''
+});
+const rules = reactive({
+    endDate: [{ required: true, message: '请选择有效期', trigger: 'change' }],
+})
+const formRef = ref<FormInstance>();
+const close = () => {
+    formRef.value?.resetFields();
+    emit('update:show', false);
+    emit('close', false);
+};
+const submitForm = async () => {
+    try {
+        await formRef.value?.validate();
+        const ids = props?.infos.map((item: any) => item.id);
+        proxy?.$modal.loading('修改中...');
+        const res = await updateOriginCpy({ ...form.value, ids }).finally(() => {
+            proxy?.$modal.closeLoading();
+        });
+        if (res?.code === 200) {
+            proxy?.$modal.msgSuccess('修改成功');
+            close();
+            emit('success', true);
+        }
+    } catch (error) {
+        console.error(error);
+    }
+};
+// mapInfoToNameString
+const mapInfoToNameString = (infos: any[]) => {
+    return infos.map((item) => item.cpyName).join('、');
+};
+watch(
+    () => props.show,
+    (val) => {
+        dialogVisible.value = val;
+    },
+    { immediate: true }
+);
+</script>

+ 142 - 0
src/views/price/models/addStation.vue

@@ -0,0 +1,142 @@
+<template>
+    <vxe-modal v-model="dialogVisible" :title="title" show-zoom resize show-footer destroy-on-close transfer @hide="close" :width="width">
+        <template #default>
+            <div class="d-flex flex-cln" style="height: 60vh;">
+                <div class="pd-16">
+                    <el-form ref="queryFormRef" :model="queryParams" inline>
+                        <el-form-item label="企业名称">
+                            <el-input v-model="queryParams.cpyName" placeholder="请输入企业名称" clearable />
+                        </el-form-item>
+                        <el-form-item>
+                            <el-button type="primary" @click="handleQuery">查询</el-button>
+                            <el-button @click="resetQuery">重置</el-button>
+                        </el-form-item>
+                    </el-form>
+                </div>
+                <div class="flex1 ov-hd">
+                    <vxe-table ref="tableRef" :loading="loading" border :data="list" height="auto" :column-config="{ resizable: true }" :row-config="{ keyField: 'id', isCurrent: true, isHover: true }" :checkbox-config="{ highlight: true, range: true, trigger: 'row', reserve: true }">
+                        <vxe-column type="checkbox" width="60"></vxe-column>
+                        <vxe-column type="seq" width="60" title="序号" align="center" />
+                        <!-- 企业名称 -->
+                        <vxe-column title="企业名称" field="cpyName" min-width="100" :formatter="colNoData" />
+                        <!-- 会员级别 -->
+                        <vxe-column title="会员级别" field="vipLevelName" min-width="100" :formatter="colNoData" />
+                        <!-- 企业地址 -->
+                        <vxe-column title="企业地址" min-width="100" :formatter="colNoData">
+                            <template #default="{ row }">{{ row.regionCodeName }}{{ row.address }}</template>
+                        </vxe-column>
+                        <!-- 单位负责人 -->
+                        <vxe-column title="单位负责人" field="contactPerson" width="90" />
+                        <!-- 负责人联系电话 -->
+                        <vxe-column title="负责人联系电话" field="tel" width="120" />
+                    </vxe-table>
+                </div>
+                <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+            </div>
+            <div class="d-flex j-c pd-16">
+                <el-form ref="formRef" :model="form" :rules="rules" label-width="auto" inline>
+                    <el-form-item label="监测点有效期至" prop="endDate">
+                        <el-date-picker v-model="form.endDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择监测点有效期至" clearable />
+                    </el-form-item>
+                </el-form>
+            </div>
+        </template>
+        <template #footer>
+            <el-button @click="close">取消</el-button>
+            <el-button type="primary" @click="submitForm">确认提交</el-button>
+        </template>
+    </vxe-modal>
+</template>
+<script setup name="addStation" lang="ts">
+import { addOriginCpy, listByPage } from '@/api/price/station';
+import { colNoData } from '@/utils/noData';
+import { propTypes } from '@/utils/propTypes';
+const emit = defineEmits(['update:show', 'close', 'sueccess']);
+const props = defineProps({
+    title: propTypes.string.def('添加监测点'),
+    width: propTypes.number.def(1200),
+    show: propTypes.bool.def(false)
+});
+const dialogVisible = ref(false);
+const { query }: any = useRoute();
+const router = useRouter();
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const list = ref<any[]>([]);
+const loading = ref(true);
+const total = ref(0);
+const queryFormRef = ref<ElFormInstance>();
+const data = reactive<any>({
+    form: {
+        endDate: ''
+    },
+    rules: {
+        endDate: [{ required: true, message: '请选择监测点有效期至', trigger: 'blur' }]
+    },
+    queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        status: '1'
+    }
+});
+const formRef = ref<ElFormInstance>();
+const { queryParams, form, rules } = toRefs(data);
+
+/** 查询会员信息列表 */
+const getList = async () => {
+    loading.value = true;
+    const res = await listByPage({ ...queryParams.value, packageId: props?.packageId });
+    list.value = res.rows;
+    total.value = res.total;
+    loading.value = false;
+};
+
+/** 搜索按钮操作 */
+const handleQuery = (level?: any) => {
+    queryParams.value.pageNum = 1;
+    getList();
+};
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+    queryFormRef.value?.resetFields();
+    queryParams.value.startDate = '';
+    queryParams.value.endDate = '';
+    handleQuery();
+};
+
+const close = () => {
+    // formRef.value?.resetFields();
+    emit('update:show', false);
+    emit('close', false);
+};
+const tableRef = ref<any>();
+const submitForm = async () => {
+    const ids = tableRef.value?.getCheckboxReserveRecords(true).concat(tableRef.value?.getCheckboxRecords());
+    if (!ids.length) {
+        proxy?.$modal.msgWarning('请选择企业');
+        return;
+    }
+    // 表单校验
+    const valid = await formRef.value?.validate();
+    if (!valid) return;
+    const cpyIds = ids.map((item: any) => item.id);
+    proxy?.$modal.loading('提交中...');
+    const res = await addOriginCpy({ cpyIds, endDate: form.value?.endDate }).finally(() => {
+        proxy?.$modal.closeLoading();
+    });
+    if (!res || res.code !== 200) return;
+    proxy?.$modal.msgSuccess('提交成功');
+    emit('sueccess', true);
+    close();
+};
+watch(
+    () => props.show,
+    (val) => {
+        dialogVisible.value = val;
+    },
+    { immediate: true }
+);
+onMounted(() => {
+    getList();
+});
+</script>

+ 4 - 0
src/views/price/models/index.ts

@@ -0,0 +1,4 @@
+export { default as addStation } from './addStation.vue'; // 添加监测点
+export { default as EditStationEndDate } from './EditStationEndDate.vue'; // 批量修改有效期
+export { default as priceRepordLog } from './priceRepordLog.vue'; // 监测点上报数据明细
+export { default as priceRepordCheck } from './priceRepordCheck.vue'; // 监测点上报数据明细审核

+ 184 - 0
src/views/price/models/priceRepordCheck.vue

@@ -0,0 +1,184 @@
+<template>
+    <div>
+        <div class="pb-16 d-flex j-sb">
+            <div>
+                <div>
+                    <searchTabs v-model="queryParams.auditStatus" @change="handleQuery" :list="tabs" key-label="name" key-value="type" key-count="num"></searchTabs>
+                </div>
+            </div>
+            <div>
+                <el-button @click="allPass" type="primary">全部通过</el-button>
+                <el-button @click="allNoPass" type="danger">全部不通过</el-button>
+            </div>
+        </div>
+        <vxe-table :loading="loading" border :data="list">
+            <!-- 序号 -->
+            <vxe-column type="seq" width="60" title="序号" align="center" />
+            <!-- 品名 -->
+            <vxe-column title="品名" field="varietyName" min-width="100" :formatter="colNoData" />
+            <!-- 规格 -->
+            <vxe-column title="规格" field="specification" min-width="100" :formatter="colNoData" />
+            <!-- 产地 -->
+            <vxe-column title="产地价格(元/kg)" field="price" min-width="100" />
+            <vxe-column title="对比近7天价格" min-width="100">
+                <template #default="{ row }">{{ row.growthRate }}%</template>
+            </vxe-column>
+            <vxe-column title="积分" field="points" width="60" :formatter="colNoData" />
+            <vxe-column title="上报人" field="createByName" width="100" :formatter="colNoData" />
+            <vxe-column title="上报时间" field="createTime" width="160" :formatter="colNoData" />
+            <vxe-column title="审核状态" fixed="right" width="110">
+                <template #default="{ row }">
+                    <div :class="['c-res-' + row?.auditStatus]">{{ selectDictLabel(check_status, row?.auditStatus) }}</div>
+                </template>
+            </vxe-column>
+            <!-- 操作 -->
+            <vxe-column title="操作" align="center" fixed="right" width="180">
+                <template #default="{ row }">
+                    <template v-if="row.auditStatus === '0'">
+                        <el-button @click.stop="passRow(row)" text type="primary">通过</el-button>
+                        <el-button @click.stop="noPassRow(row)" text type="danger">不通过</el-button>
+                    </template>
+                </template>
+            </vxe-column>
+        </vxe-table>
+    </div>
+    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+</template>
+<script setup name="priceRepordCheck" lang="ts">
+import { colNoData } from '@/utils/noData';
+import { listVipPayment } from '@/api/dgtmedicine/vipPayment/index';
+import { approvalPrice, originPriceDetail, priceDetailCount } from '@/api/price/report';
+import { searchTabs } from '@/views/models';
+const { query }: any = useRoute()
+const router = useRouter();
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { check_status } = toRefs<any>(proxy?.useDict('check_status'));
+// 字典
+const list = ref<any[]>([]);
+const loading = ref(true);
+const total = ref(0);
+const queryFormRef = ref<ElFormInstance>();
+const data = reactive<any>({
+    queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        auditStatus: '0'
+    }
+});
+const { queryParams } = toRefs(data);
+/** 点击行上传发票 */
+
+/** 查询会员信息列表 */
+const getList = async () => {
+    loading.value = true;
+    const res = await originPriceDetail({ ...queryParams.value, originPriceId: query?.id, cpyid: query?.cpyid });
+    list.value = res.rows;
+    total.value = res.total;
+    loading.value = false;
+};
+/** 搜索按钮操作 */
+const handleQuery = (level?: any) => {
+    queryParams.value.pageNum = 1;
+    getList();
+};
+/** 重置按钮操作 */
+const resetQuery = () => {
+    queryFormRef.value?.resetFields();
+    handleQuery();
+};
+// tabs count获取
+const tabs = ref<any>([]);
+const getTabs = async () => {
+    const res = await priceDetailCount({ originPriceId: query?.id, cpyid: query?.cpyid });
+    if (!res || res.code !== 200) return;
+    tabs.value = res.data
+};
+const allPass = async () => {
+    const confirm = await proxy?.$modal.confirm('是否确认将本次上报品种的产地价格审核为通过?');
+    if (confirm === 'confirm') {
+        const params = {
+            priceId: query?.id,
+            auditStatus: '1',
+        }
+        auditSubmit(params);
+    }
+};
+const allNoPass = async () => {
+    ElMessageBox.prompt('<div>是否确认将本次上报的全部品种产地价格审核为不通过!</div><div>不通理由:</div>', '审核不通过', {
+        confirmButtonText: '确认不通过',
+        cancelButtonText: '取消',
+        dangerouslyUseHTMLString: true,
+        inputValidator: (value: any) => {
+            if (!value) {
+                return '请填写不通过理由';
+            }
+        },
+        inputPlaceholder: '请填写不通过理由...',
+        inputErrorMessage: '请填写不通过理由...',
+    })
+        .then(({ value }) => {
+            console.log('确认', value);
+            const params = {
+                priceId: query?.id,
+                auditStatus: '2',
+                msg: value
+        }
+        auditSubmit(params);
+        })
+        .catch(() => {
+            console.log('取消');
+
+        })
+};
+const passRow = async (row: any) => {
+    const confirm = await proxy?.$modal.confirm(`是否确认将本次上报品种${row?.varietyName}的产地价格审核为通过?`);
+    if (confirm === 'confirm') {
+        console.log('confirm');
+        const params = {
+            targetIds: [row.id],
+            auditStatus: '1',
+        }
+        auditSubmit(params);
+    }
+};
+const noPassRow = async (row: any) => {
+    ElMessageBox.prompt(`<div>是否确认将品种${row?.varietyName}的产地价格审核为不通过!</div><div>不通理由:</div>`, '审核不通过', {
+        confirmButtonText: '确认不通过',
+        cancelButtonText: '取消',
+        dangerouslyUseHTMLString: true,
+        inputValidator: (value: any) => {
+            if (!value) {
+                return '请填写不通过理由';
+            }
+        },
+        inputPlaceholder: '请填写不通过理由...',
+        inputErrorMessage: '请填写不通过理由...',
+    })
+        .then(({ value }) => {
+            const params = {
+                targetIds: [row.id],
+                auditStatus: '2',
+                msg: value
+            }
+            auditSubmit(params);
+        })
+        .catch(() => {
+            console.log('取消');
+        })
+};
+// 审核提交
+const auditSubmit = async (params) => {
+    proxy?.$modal.loading('审核中...');
+    const res = await approvalPrice(params).finally(() => {
+        proxy?.$modal.closeLoading();
+    });
+    if (!res || res.code !== 200) return;
+    proxy?.$modal.msgSuccess('审核成功');
+    getList();
+};
+
+onMounted(() => {
+    getTabs();
+    getList();
+});
+</script>

+ 71 - 0
src/views/price/models/priceRepordLog.vue

@@ -0,0 +1,71 @@
+<template>
+    <div>
+        <vxe-table :loading="loading" border :data="list">
+            <!-- 序号 -->
+            <vxe-column type="seq" width="60" title="序号" align="center" />
+            <!-- 品名 -->
+            <vxe-column title="品名" field="varietyName" min-width="100" :formatter="colNoData" />
+            <!-- 规格 -->
+            <vxe-column title="规格" field="specification" min-width="100" :formatter="colNoData" />
+            <!-- 产地 -->
+            <vxe-column title="产地价格(元/kg)" field="price" min-width="100" />
+            <vxe-column title="对比近7天价格" min-width="100">
+                <template #default="{ row }">{{ row.growthRate }}%</template>
+            </vxe-column>
+            <vxe-column title="积分" field="points" width="60" :formatter="colNoData" />
+            <vxe-column title="上报人" field="createByName" width="100" :formatter="colNoData" />
+            <vxe-column title="上报时间" field="createTime" min-width="100" :formatter="colNoData" />
+            <vxe-column title="状态" fixed="right" width="110">
+                <template #default="{ row }">
+                    <div :class="['c-res-' + row?.auditStatus]">{{ selectDictLabel(check_status, row?.auditStatus) }}</div>
+                </template>
+            </vxe-column>
+        </vxe-table>
+    </div>
+    <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+</template>
+<script setup name="priceRepordLog" lang="ts">
+import { colNoData } from '@/utils/noData';
+import { listVipPayment } from '@/api/dgtmedicine/vipPayment/index';
+import { originPriceDetail } from '@/api/price/report';
+const { query }: any = useRoute()
+const router = useRouter();
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { check_status } = toRefs<any>(proxy?.useDict('check_status'));
+// 字典
+const list = ref<any[]>([]);
+const loading = ref(true);
+const total = ref(0);
+const queryFormRef = ref<ElFormInstance>();
+const data = reactive<any>({
+    queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+    }
+});
+const { queryParams } = toRefs(data);
+/** 点击行上传发票 */
+
+/** 查询会员信息列表 */
+const getList = async () => {
+    loading.value = true;
+    const res = await originPriceDetail({ ...queryParams.value, cpyid: query?.cpyid });
+    list.value = res.rows;
+    total.value = res.total;
+    loading.value = false;
+};
+/** 搜索按钮操作 */
+const handleQuery = (level?: any) => {
+    queryParams.value.pageNum = 1;
+    getList();
+};
+/** 重置按钮操作 */
+const resetQuery = () => {
+    queryFormRef.value?.resetFields();
+    handleQuery();
+};
+
+onMounted(() => {
+    getList();
+});
+</script>

+ 77 - 0
src/views/price/report/detail/index.vue

@@ -0,0 +1,77 @@
+<template>
+    <div class="p-3">
+        <div class="bg-fff flex1 ov-hd d-flex flex-cln">
+            <div class="d-flex a-c pd-16" style="padding-bottom: 0;">
+                <div class="f-s-20 c-333 f-w-7 mr-10">上报详情</div>
+                <el-button @click="router.go(-1)" type="primary" text>
+                    <el-icon>
+                        <Back />
+                    </el-icon>
+                    返回上一级
+                </el-button>
+            </div>
+            <div class="pd-16 border-bottom">
+                <div class="info-title f-w-5 mb-10">上报基本信息</div>
+                <el-descriptions :column="4">
+                    <el-descriptions-item label="上报品种:">{{ form?.varietyName || '-' }}</el-descriptions-item>
+                    <el-descriptions-item label="上报企业:">{{ form?.cpyName || '-' }}</el-descriptions-item>
+                    <el-descriptions-item label="所在区域:">{{ form?.regionCodeName }}{{ form?.address || '-' }}</el-descriptions-item>
+                    <el-descriptions-item label="联系方式:">{{ form?.tel || '-' }}</el-descriptions-item>
+                    <el-descriptions-item label="上报说明:">{{ form?.remark || '-' }}</el-descriptions-item>
+                    <el-descriptions-item label="上报人:">{{ form?.createByName || '-' }}</el-descriptions-item>
+                    <el-descriptions-item label="上报时间:">{{ form?.createTime || '-' }}</el-descriptions-item>
+                </el-descriptions>
+            </div>
+            <div class="flex1 over-auto">
+                <div class="pd-16">
+                    <div class="info-title mb-16 f-w-5">上报产地价格信息</div>
+                    <priceRepordCheck></priceRepordCheck>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup name="Station-detail" lang="ts">
+import { originCpyInfo } from '@/api/price/station';
+import { priceRepordCheck } from '../../models';
+import { originPriceDetailInfo } from '@/api/price/report';
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { query }:any = useRoute()
+const router = useRouter();
+const form = ref<any>(null);
+const getDetail = async () => {
+    proxy.$modal.loading('加载中...')
+    const res = await originPriceDetailInfo(query?.id).finally(() => proxy.$modal.closeLoading());
+    if (!res || res.code !== 200) return;
+    form.value = res.data;
+};
+const tabs = ref([
+    { label: '订单信息', value: '1' },
+    { label: '套餐信息', value: '2' },
+])
+onMounted(() => {
+    getDetail()
+});
+</script>
+<style lang="scss" scoped>
+.tabs-item {
+    margin-right: 20px;
+   padding: 8px 20px;
+   font-size: 14px;
+   border-color:  #d7d7d7;
+   border-style: solid;
+   border-width: 1px 1px 0 1px;
+   cursor: pointer;
+   user-select: none;
+
+   &.checked {
+    color: #fff;
+    border-color: var(--el-color-primary);
+    background-color: var(--el-color-primary);
+   }
+}
+.border-botttom {
+    border-bottom: 1px solid #d7d7d7;
+}
+</style>

+ 100 - 0
src/views/price/report/index.vue

@@ -0,0 +1,100 @@
+<template>
+    <div class="p-3">
+        <div class="bg-fff flex1 ov-hd d-flex flex-cln">
+            <div class="pd-16 border-bottom">
+                <div class="f-s-20 c-333 f-w-7 mb-20">上报价格审核</div>
+                <div class="d-flex j-ed">
+                    <div class="d-flex pl-20">
+                        <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="auto">
+                            <el-form-item label="品种名称">
+                                <el-input v-model="queryParams.varietyName" placeholder="搜品种名称" clearable />
+                            </el-form-item>
+                            <el-form-item label="企业名称">
+                                <el-input v-model="queryParams.cpyName" placeholder="搜企业名称" clearable />
+                            </el-form-item>
+                            <el-form-item label="审核状态">
+                                <el-select v-model="queryParams.auditStatus" @change="handleQuery" placeholder="请选择审核状态" clearable>
+                                    <el-option v-for="item in check_status" :key="item.value" :label="item.label" :value="item.value" />
+                                </el-select>
+                            </el-form-item>
+                            <el-form-item>
+                                <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+                                <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+                            </el-form-item>
+                        </el-form>
+                    </div>
+                </div>
+            </div>
+            <div class="flex1 ov-hd pd-16 d-flex flex-cln">
+                <div class="flex1 ov-hd">
+                    <vxe-table ref="tableRef" :loading="loading" border :data="list" min-height="0" max-height="auto" :column-config="{ resizable: true }">
+                        <!-- 序号 -->
+                        <vxe-column type="seq" width="60" title="序号" align="center" />
+                        <vxe-column title="上报品种" field="varietyName" min-width="100" :formatter="colNoData" />
+                        <vxe-column title="上报企业" field="cpyName" min-width="100" :formatter="colNoData" />
+                        <vxe-column title="所在区域" field="originName" min-width="100" :formatter="colNoData" />
+                        <vxe-column title="联系方式" field="tel" width="110" :formatter="colNoData" />
+                        <vxe-column title="上报说明" field="remark" min-width="100" :formatter="colNoData" />
+                        <vxe-column title="上报人" field="createByName" width="90" :formatter="colNoData" />
+                        <vxe-column title="上报时间" field="createTime" width="160" :formatter="colNoData" />
+                        <vxe-column title="规格数" field="specCount" width="80" :formatter="colNoData" />
+                        <vxe-column title="待审核数" field="waitCount" width="80" />
+                        <vxe-column title="已通过/不通过" width="120">
+                            <template #default="{ row }">
+                                <el-tag class="mr-10" type="primary">{{ row?.agreeCount }}</el-tag>
+                                <el-tag type="danger">{{ row?.refuseCount }}</el-tag>
+                            </template>
+                        </vxe-column>
+                        <vxe-column title="操作" align="center" fixed="right" width="100">
+                            <template #default="{ row }">
+                                <el-button @click="router.push({ path: 'report-detail', query: { id: row?.id, cpyid: row?.cpyid } })" type="primary" text>详情</el-button>
+                            </template>
+                        </vxe-column>
+                    </vxe-table>
+                </div>
+            </div>
+            <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+            <div class="pd-5"></div>
+        </div>
+    </div>
+</template>
+<script setup name="price-report" lang="ts">
+import { colNoData } from '@/utils/noData';
+import NP from 'number-precision';
+import { originPriceList } from '@/api/price/report';
+const router = useRouter();
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { check_status } = toRefs<any>(proxy?.useDict('check_status'));
+const queryParams = ref<any>({
+    pageNum: 1,
+    pageSize: 10,
+    auditStatus: '0'
+});
+const loading = ref(false);
+const total = ref(0);
+const list = ref<any>([]);
+const getList = async () => {
+    loading.value = true;
+    const res = await originPriceList(queryParams.value);
+    if (!res || res.code !== 200) return;
+    list.value = res.rows;
+    total.value = res.total;
+    loading.value = false;
+};
+const handleQuery = () => {
+    queryParams.value.pageNum = 1;
+    getList();
+};
+const queryFormRef = ref<any>();
+const resetQuery = () => {
+    queryFormRef.value?.resetFields();
+    handleQuery();
+};
+
+const tableRef = ref<any>();
+
+onMounted(() => {
+
+    handleQuery();
+});
+</script>

+ 80 - 0
src/views/price/station/detail/index.vue

@@ -0,0 +1,80 @@
+<template>
+    <div class="p-3">
+        <div class="bg-fff flex1 ov-hd d-flex flex-cln">
+            <div class="d-flex a-c pd-16">
+                <div class="f-s-20 c-333 f-w-7 mr-10">监测点详情</div>
+                <el-button @click="router.go(-1)" type="primary" text>
+                    <el-icon>
+                        <Back />
+                    </el-icon>
+                    返回上一级
+                </el-button>
+            </div>
+            <div class="pd-16 border-bottom">
+                <div class="info-title f-w-5 mb-10">基本信息</div>
+                <el-descriptions :column="4">
+                    <el-descriptions-item label="企业名称:">{{ form?.cpyName || '-' }}</el-descriptions-item>
+                    <el-descriptions-item label="企业地址:">{{ form?.regionCodeName }}{{ form?.address || '-' }}</el-descriptions-item>
+                    <el-descriptions-item label="单位负责人:">{{ form?.contactPerson || '-' }}</el-descriptions-item>
+                    <el-descriptions-item label="负责人联系电话:">{{ form?.tel || '-' }}</el-descriptions-item>
+                    <el-descriptions-item label="有效期状态:">
+                        <el-tag v-if="+form?.isValid" type="success">有效</el-tag>
+                        <el-tag v-else type="danger">已过期</el-tag>
+                    </el-descriptions-item>
+                    <el-descriptions-item label="有效期至:">{{ form?.endDate || '-' }}</el-descriptions-item>
+                    <el-descriptions-item label="操作人:">{{ form?.createByName || '-' }}</el-descriptions-item>
+                    <el-descriptions-item label="操作时间:">{{ form?.createTime || '-' }}</el-descriptions-item>
+                </el-descriptions>
+            </div>
+            <div class="flex1 over-auto">
+                <div class="pd-16">
+                    <div class="info-title mb-16 f-w-5">上报产地价格信息</div>
+                    <priceRepordLog></priceRepordLog>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script setup name="Station-detail" lang="ts">
+import { originCpyInfo } from '@/api/price/station';
+import { priceRepordLog } from '../../models';
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { query }:any = useRoute()
+const router = useRouter();
+const form = ref<any>(null);
+const getDetail = async () => {
+    proxy.$modal.loading('加载中...')
+    const res = await originCpyInfo(query?.id).finally(() => proxy.$modal.closeLoading());
+    if (!res || res.code !== 200) return;
+    form.value = res.data;
+};
+const tabs = ref([
+    { label: '订单信息', value: '1' },
+    { label: '套餐信息', value: '2' },
+])
+onMounted(() => {
+    getDetail()
+});
+</script>
+<style lang="scss" scoped>
+.tabs-item {
+    margin-right: 20px;
+   padding: 8px 20px;
+   font-size: 14px;
+   border-color:  #d7d7d7;
+   border-style: solid;
+   border-width: 1px 1px 0 1px;
+   cursor: pointer;
+   user-select: none;
+
+   &.checked {
+    color: #fff;
+    border-color: var(--el-color-primary);
+    background-color: var(--el-color-primary);
+   }
+}
+.border-botttom {
+    border-bottom: 1px solid #d7d7d7;
+}
+</style>

+ 165 - 0
src/views/price/station/index.vue

@@ -0,0 +1,165 @@
+<template>
+    <div class="p-3">
+        <div class="bg-fff flex1 ov-hd d-flex flex-cln">
+            <div class="pd-16 border-bottom">
+                <div class="f-s-20 c-333 f-w-7 mb-20">监测点管理</div>
+                <div class="d-flex j-sb">
+                    <el-button type="primary" @click="showStation = true">添加监测点</el-button>
+                    <div class="d-flex pl-20">
+                        <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="auto">
+                            <el-form-item label="企业名称">
+                                <el-input v-model="queryParams.cpyName" placeholder="请输入企业名称" clearable />
+                            </el-form-item>
+                            <el-form-item>
+                                <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+                                <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+                            </el-form-item>
+                        </el-form>
+                    </div>
+                </div>
+            </div>
+            <div class="flex1 ov-hd pd-16 d-flex flex-cln">
+                <div class="d-flex j-sb mb-16">
+                    <div><searchTabs v-model="queryParams.isValid" @change="handleQuery" :list="tabs" key-label="name" key-value="type" key-count="num"></searchTabs></div>
+                    <div>
+                        <el-button @click="batchUpdateEndDate" type="primary">批量修改有效期</el-button>
+                        <el-button @click="batchDelete" type="danger">批量删除</el-button>
+                    </div>
+                </div>
+                <div class="flex1 ov-hd">
+                    <vxe-table ref="tableRef" :loading="loading" border :data="list" min-height="0" max-height="auto" :column-config="{ resizable: true }" :row-config="{keyField: 'id',isCurrent: true, isHover: true}" :checkbox-config="{ highlight: true, range: true, trigger: 'row', reserve: true }">
+                        <vxe-column type="checkbox" width="60"></vxe-column>
+                        <!-- 序号 -->
+                        <vxe-column type="seq" width="60" title="序号" align="center" />
+                        <!-- 企业名称 -->
+                        <vxe-column title="企业名称" field="cpyName" min-width="100" />
+                        <!-- 企业地址 -->
+                        <vxe-column title="企业地址" min-width="100" :formatter="colNoData">
+                            <template #default="{ row }">{{ row.regionCodeName }}{{ row.address }}</template>
+                        </vxe-column>
+                        <!-- 单位负责人 -->
+                        <vxe-column title="单位负责人" field="contactPerson" width="90" />
+                        <!-- 负责人联系电话 -->
+                        <vxe-column title="负责人联系电话" field="tel" width="120" />
+                        <vxe-column title="有效期状态" width="90">
+                            <template #default="{ row }">
+                                <el-tag v-if="+row.isValid" type="success">有效</el-tag>
+                                <el-tag v-else type="danger">已过期</el-tag>
+                            </template>
+                        </vxe-column>
+                        <vxe-column title="有效期至" field="endDate" min-width="100" width="110" />
+                        <vxe-column title="操作人" field="createByName" min-width="100" :formatter="colNoData" />
+                        <vxe-column title="操作时间" field="createTime" min-width="100" :formatter="colNoData" />
+                        <vxe-column title="操作" align="center" fixed="right" width="240">
+                            <template #default="{ row }">
+                                <el-button @click.stop="router.push({ path: 'station-detail', query: { id: row?.id, cpyid: row?.cpyid } })" text type="primary">详情</el-button>
+                                <span></span>
+                                <el-button @click.stop="updateEndDateItem(row)" text style="color: #0079fe">修改有效期</el-button>
+                                <span></span>
+                                <el-button @click.stop="deleteItem(row)" text type="danger">删除</el-button>
+                            </template>
+                        </vxe-column>
+                    </vxe-table>
+                </div>
+            </div>
+            <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+            <div class="pd-5"></div>
+        </div>
+    </div>
+    <addStation v-model:show="showStation" @sueccess="handleQuery"></addStation>
+    <EditStationEndDate v-if="showEndDate" v-model:show="showEndDate" :infos="infos" @sueccess="handleQuery"></EditStationEndDate>
+</template>
+<script setup name="price-station" lang="ts">
+import { deleteOriginCpy, originCpyList, queryOriginCpyCount } from '@/api/price/station';
+import { colNoData } from '@/utils/noData';
+import { searchTabs } from '@/views/models';
+import NP from 'number-precision';
+import { addStation, EditStationEndDate } from '../models';
+const router = useRouter();
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const queryParams = ref<any>({
+    pageNum: 1,
+    pageSize: 10,
+    isValid: '1'
+});
+const showEndDate = ref(false);
+const showStation = ref(false);
+const loading = ref(false);
+const total = ref(0);
+const list = ref<any>([]);
+const getList = async () => {
+    loading.value = true;
+    const res = await originCpyList(queryParams.value);
+    if (!res || res.code !== 200) return;
+    list.value = res.rows;
+    total.value = res.total;
+    loading.value = false;
+};
+const handleQuery = () => {
+    queryParams.value.pageNum = 1;
+    getList();
+};
+const queryFormRef = ref<any>();
+const resetQuery = () => {
+    queryFormRef.value?.resetFields();
+    handleQuery();
+};
+// tabs count获取
+const tabs = ref<any>([]);
+const getTabs = async () => {
+    const res = await queryOriginCpyCount();
+    if (!res || res.code !== 200) return;
+    tabs.value = res.data
+};
+const tableRef = ref<any>();
+// 批量删除
+const batchDelete = async () => {
+    const records = tableRef.value?.getCheckboxReserveRecords(true).concat(tableRef.value?.getCheckboxRecords());
+    if (!records.length) {
+        proxy?.$modal.msgWarning('请选择监测点');
+        return;
+    }
+    const confirm = await proxy?.$modal.confirm('是否确认删除监测点,删除后企业上报的数据将不再作为专业数据展示,之前上报的数据不受影响。');
+    const ids = records.map((item: any) => item.id);
+    if (confirm === 'confirm') {
+        deleteSubmit(ids)
+    }
+};
+const deleteItem = async (row: any) => {
+    const confirm = await proxy?.$modal.confirm('是否确认删除该监测点,删除后该企业上报的数据将不再作为专业数据展示,之前上报的数据不受影响。');
+    if (confirm === 'confirm') {
+        deleteSubmit([row.id])
+    }
+};
+// 删除提交
+const deleteSubmit = async (ids: string[]) => {
+    proxy?.$modal.loading('删除中...');
+    const res = await deleteOriginCpy(ids).finally(() => {
+        proxy?.$modal.closeLoading();
+    });
+    if (!res || res.code !== 200) return;
+    proxy?.$modal.msgSuccess('删除成功');
+    handleQuery();
+};
+// 修改有效期的检测点
+const infos = ref<any[]>([]);
+// 修改有效期
+const updateEndDateItem = async (row: any) => {
+    infos.value = [row];
+    showEndDate.value = true;
+};
+// 批量修改有效期
+const batchUpdateEndDate = async () => {
+    const records = tableRef.value?.getCheckboxReserveRecords(true).concat(tableRef.value?.getCheckboxRecords());
+    if (!records.length) {
+        proxy?.$modal.msgWarning('请选择监测点');
+        return;
+    }
+    infos.value = records;
+    showEndDate.value = true;
+};
+onMounted(() => {
+    getTabs();
+    handleQuery();
+});
+</script>