huangxw 10 ماه پیش
والد
کامیت
cebde64c37

+ 6 - 4
.prettierrc

@@ -1,16 +1,18 @@
 {
   "printWidth": 150,
-  "tabWidth": 2,
+  "tabWidth": 4,
   "useTabs": false,
   "semi": true,
   "singleQuote": true,
-  "quoteProps": "preserve",
+  "quoteProps": "as-needed",
   "jsxSingleQuote": false,
-  "bracketSameLine": false,
   "trailingComma": "none",
   "bracketSpacing": true,
-  "embeddedLanguageFormatting": "auto",
+  "jsxBracketSameLine": false,
+  "embeddedLanguageFormatting": "off",
   "arrowParens": "always",
+  "rangeStart": 0,
+  "rangeEnd": "Infinity",
   "requirePragma": false,
   "insertPragma": false,
   "proseWrap": "preserve",

+ 1 - 1
src/api/dgtmedicine/member/index.ts

@@ -57,7 +57,7 @@ export const updateMember = (data: MemberForm) => {
  */
 export const delMember = (id: string | number | Array<string | number>) => {
   return request({
-    url: '/dgtmedicine/member/remove/' + id,
+    url: '/dgtmedicine/member/del/' + id,
     method: 'get'
   });
 };

+ 3 - 4
src/components/FileUpload/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="upload-file">
+  <div class="upload-file flex1">
     <el-upload
       ref="fileUploadRef"
       multiple
@@ -30,7 +30,7 @@
     </div>
     <!-- 文件列表 -->
     <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul">
-      <li v-for="(file, index) in fileList" :key="file.uid" class="el-upload-list__item ele-upload-list__item-content">
+      <li v-for="(file, index) in fileList" :key="file.uid" class="el-upload-list__item ele-upload-list__item-content pd-8">
         <el-link :href="`${file.url}`" :underline="false" target="_blank">
           <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
         </el-link>
@@ -44,9 +44,8 @@
 
 <script setup lang="ts">
 import { propTypes } from '@/utils/propTypes';
-import { delOss, listByIds } from '@/api/system/oss';
+import { delOss, listByIds } from '@/api/system/oss/index';
 import { globalHeaders } from '@/utils/request';
-
 const props = defineProps({
   modelValue: {
     type: [String, Object, Array],

+ 5 - 7
src/layout/components/AppMain.vue

@@ -1,11 +1,9 @@
 <template>
   <section class="app-main">
     <router-view v-slot="{ Component, route }">
-      <transition v-if="!route.meta.noCache" :enter-active-class="animante" mode="out-in">
-        <keep-alive v-if="!route.meta.noCache" :include="tagsViewStore.cachedViews">
-          <component :is="Component" v-if="!route.meta.link" :key="route.path" />
-        </keep-alive>
-      </transition>
+      <keep-alive v-if="!route.meta.noCache" :include="tagsViewStore.cachedViews">
+        <component :is="Component" v-if="!route.meta.link" :key="route.path" />
+      </keep-alive>
       <transition v-if="route.meta.noCache" :enter-active-class="animante" mode="out-in">
         <component :is="Component" v-if="!route.meta.link && route.meta.noCache" :key="route.path" />
       </transition>
@@ -64,7 +62,7 @@ function addIframe() {
   background-color: #f5f5f5;
 }
 
-.fixed-header + .app-main {
+.fixed-header+.app-main {
   padding-top: 50px;
 }
 
@@ -74,7 +72,7 @@ function addIframe() {
     min-height: calc(100vh - 84px);
   }
 
-  .fixed-header + .app-main {
+  .fixed-header+.app-main {
     padding-top: 84px;
   }
 }

+ 63 - 331
src/views/dgtmedicine/member/index.vue

@@ -17,15 +17,16 @@
               @keyup.enter="handleQuery" />
           </el-form-item>
           <el-form-item label="入会时间段" prop="dateRange">
-            <el-date-picker style="width: 200px" clearable v-model="queryParams.dateRange" type="daterange"
-              range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD"
-              @change="handleDateRangeChange" />
+            <div class="d-flex" style="width: 180px">
+              <DateRange v-model="queryParams.dateRange" v-model:start-date="queryParams.payStartDate"
+                v-model:end-date="queryParams.payEndDate"></DateRange>
+            </div>
           </el-form-item>
-          <el-form-item label="有效期状态" prop="cpyName">
-            <el-select style="width: 140px" v-model="queryParams.vipLevel" clearable placeholder="搜有效期状态">
+          <el-form-item label="有效期状态" prop="vipEnable">
+            <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="2"></el-option>
+              <el-option label="过期" value="0"></el-option>
             </el-select>
           </el-form-item>
           <el-form-item>
@@ -35,17 +36,10 @@
         </el-form>
       </div>
 
-      <!-- <template #header>
-        <el-row :gutter="20" class="mb8">
-          <el-col :span="2" v-for="level in memberLevelCountList" :key="level.type">
-            <el-button type="text" @click="handleQuery(level)"
-              :style="{ fontWeight: queryParams.vipLevel === level.type ? 'bold' : 'normal', color: queryParams.vipLevel === level.type ? 'black' : 'inherit' }">{{
-                level.name }}({{ level.num }})</el-button>
-          </el-col>
-          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-        </el-row>
-      </template> -->
       <div class="d-flex flex1 ov-hd flex-cln pd-16">
+        <searchTabs :list="memberLevelCountList" v-model="queryParams.vipLevel" keyLabel="name" @change="handleQuery"
+          keyCount="num" keyValue="type"></searchTabs>
+        <div class="pd-8"></div>
         <div class="flex1 ov-hd">
           <vxe-table :loading="loading" border :data="memberList" min-height="0" max-height="100%">
             <vxe-column title="会员名称" align="center" field="cpyName" width="220" :formatter="colNoData" />
@@ -54,209 +48,57 @@
                 <dict-tag :value="scope.row.vipLevel" :options="vip_level" />
               </template>
             </vxe-column>
-            <vxe-column title="单位负责人" align="center" field="contact" min-width="100" :formatter="colNoData" />
+            <vxe-column title="单位负责人" align="center" field="contact" width="100" :formatter="colNoData" />
             <vxe-column title="负责人联系电话" align="center" field="contactTel" wmin-width="100" :formatter="colNoData" />
-            <vxe-column title="企业地址" align="center" field="adcdDesc" wmin-width="100" :formatter="colNoData" />
-            <vxe-column title="有效期状态" align="center" field="adcdDesc" wmin-width="100" :formatter="colNoData" />
-            <vxe-column title="有效期至" align="center" field="adcdDesc" wmin-width="100" :formatter="colNoData" />
-            <vxe-column title="入会时间" align="center" field="adcdDesc" wmin-width="100" :formatter="colNoData" />
-            <vxe-column title="操作" align="center" class-name="small-padding fixed-width">
-              <template #default="scope">
-                <el-button link type="primary" @click="showApp(scope.row)"
-                  v-if="scope.row.reviewStatus == '0'">审批</el-button>
-                <el-button link type="primary" @click="memberDetail(scope.row)"
-                  v-if="scope.row.reviewStatus != '0'">详情</el-button>
+            <vxe-column title="企业地址" wmin-width="100">
+              <template #default="{ row }">
+                {{ (row.adcdCodeName || '') + (row.address || '') || '-' }}
+              </template>
+            </vxe-column>
+            <vxe-column title="有效期状态" width="100" :formatter="colNoData">
+              <template #default="{ row }">
+                {{ +row?.vipEnable ? '有效' : '过期' }}
+              </template>
+            </vxe-column>
+            <vxe-column title="有效期至" align="center" field="endDate" width="140" :formatter="colNoData" />
+            <vxe-column title="入会时间" align="center" field="startDate" wmin-width="100" :formatter="colNoData" />
+            <vxe-column title="操作" width="330" fixed="right" class-name="small-padding fixed-width">
+              <template #default="{ row }">
+                <el-button text type="primary" @click="memberDetail(row)">详情</el-button>
+                <span></span>
+                <el-button text style="color: #0079fe">修改有效期</el-button>
+                <span></span>
+                <el-button text style="color: #0079fe">修改级别</el-button>
+                <span></span>
+                <el-button text type="danger" @click="deleteItem(row)">删除</el-button>
               </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" />
+        <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
+          v-model:limit="queryParams.pageSize" @pagination="getList" />
       </div>
     </div>
-
-    <!--审核弹窗-->
-    <el-dialog :close-on-click-modal="false" :title="dialogApproval.title" v-model="dialogApproval.visible" width="1200px" append-to-body>
-      <el-form ref="memberFormRef" :model="form" :rules="rules">
-        <el-row :gutter="20">
-          <el-col :span="8">
-            <el-form-item label="企业名称" prop="cpyName">
-              <el-text v-model="form.cpyName">{{ form.cpyName }}</el-text>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="法人姓名" prop="legalPersonName">
-              <el-text>{{ form.legalPersonName }}</el-text>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="法人电话" prop="legalPersonPhone">
-              <el-text>{{ form.legalPersonPhone }}</el-text>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
-          <el-col :span="8">
-            <el-form-item label="法人职务" prop="legalPersonPosition">
-              <el-text>{{ form.legalPersonPosition }}</el-text>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="法人身份证正面图片" prop="legalPersonIdFront">
-              <el-image :src="form.legalPersonIdFront" style="width: 100px; height: 100px" show-progress
-                :preview-src-list="[form.legalPersonIdFront]" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="法人身份证背面图片" prop="legalPersonIdBack">
-              <el-image :src="form.legalPersonIdBack" style="width: 100px; height: 100px" show-progress
-                :preview-src-list="[form.legalPersonIdBack]" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
-          <el-col :span="8">
-            <el-form-item label="申请会员等级" prop="applyLevel">
-              <dict-tag :value="form.applyLevel" :options="vip_level" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="邮箱" prop="email">
-              <el-text>{{ form.email }}</el-text>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="主管部门" prop="department">
-              <el-text>{{ form.department }}</el-text>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
-          <el-col :span="8">
-            <el-form-item label="总资产" prop="totalAssets">
-              <el-text>{{ form.totalAssets }}</el-text>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="单位简介" prop="introduction">
-              <el-text>{{ form.introduction }}</el-text>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="入会目的" prop="membershipPurpose">
-              <el-text>{{ form.membershipPurpose }}</el-text>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
-          <el-col :span="8">
-            <el-form-item label="当前会员等级" prop="vipLevel">
-              <dict-tag :value="form.vipLevel" :options="vip_level" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="开始时间" prop="startDate">
-              <el-text>{{ form.startDate }}</el-text>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="结束时间" prop="endDate">
-              <el-text>{{ form.endDate }}</el-text>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-table v-loading="loading" :data="form.plantingInfo">
-          <vxe-column label="品种名称" align="center" prop="variety" />
-          <vxe-column label="种植面积" align="center" prop="plantingArea" />
-          <vxe-column label="种植地点" align="center" prop="plantingPlace" />
-        </el-table>
-        <el-row :gutter="20">
-          <el-col>
-            <el-form-item label="荣誉证书" prop="companyCertificate">
-              <el-image :src="form.companyCertificate" style="width: 100px; height: 100px" show-progress
-                :preview-src-list="form.companyCertificate" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-      <el-form ref="approvalLogFormRef" :model="approvalForm" :rules="approvalRules" label-width="80px">
-        <el-form-item label="审批类型" prop="reviewStatus">
-          <el-select v-model="approvalForm.reviewStatus" placeholder="请选择" clearable style="width: 100%"
-            @change="showRefuse">
-            <template v-for="dict in cpy_res_status">
-              <el-option v-if="dict.value != '0'" :key="dict.value" :label="dict.label" :value="dict.value" />
-            </template>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="审批理由" prop="msg" v-if="refuseShow">
-          <el-input type="textarea" v-model="approvalForm.reviewMsg" placeholder="请输入拒绝理由" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button :loading="buttonLoading" type="primary" @click="confirmApp">确 定</el-button>
-          <el-button @click="cancelApp">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
   </div>
 </template>
 
 <script setup name="Member" lang="ts">
-import { listMember, getMember, delMember, addMember, updateMember, countLevelMember } from '@/api/dgtmedicine/member/index';
-import { approvalMember } from '@/api/dgtmedicine/approvalLog';
+import { listMember, delMember, addMember, updateMember, countLevelMember } from '@/api/dgtmedicine/member/index';
+import { approvalMember } from '@/api/dgtmedicine/approvalLog/index';
 import { MemberVO, MemberQuery, MemberForm, MemberLevelCountVO } from '@/api/dgtmedicine/member/types';
 import { ApprovalLogQuery, ApprovalLogForm } from '@/api/dgtmedicine/approvalLog/types';
-import { useRouter } from 'vue-router';
 import { colNoData } from '@/utils/noData';
+import { DateRange, searchTabs } from '@/views/models/index';
 const router = useRouter();
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
 const { cpy_res_status, vip_level } = toRefs<any>(proxy?.useDict('cpy_res_status', 'vip_level'));
 const memberList = ref<MemberVO[]>([]);
 const memberLevelCountList = ref<MemberLevelCountVO[]>([]);
-const buttonLoading = ref(false);
 const loading = ref(true);
 const showSearch = ref(true);
-const refuseShow = ref(false);
 const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
 const total = ref(0);
-const approvalLogFormRef = ref<ElFormInstance>();
-
 const queryFormRef = ref<ElFormInstance>();
-const memberFormRef = ref<ElFormInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const initFormApprovalData: ApprovalLogForm = {
-  id: undefined,
-  targetType: undefined,
-  reviewStatus: '1',
-  reviewMsg: undefined
-};
-
-const dialogApproval = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const approvalData = reactive<PageData<ApprovalLogForm, ApprovalLogQuery>>({
-  form: { ...initFormApprovalData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    targetType: undefined,
-    targetId: undefined,
-    res: undefined,
-    msg: undefined,
-    params: {}
-  },
-  rules: {}
-});
 
 const initFormData: MemberForm = {
   id: undefined,
@@ -289,23 +131,15 @@ const data = reactive<any>({
   form: { ...initFormData },
   queryParams: {
     pageNum: 1,
-    pageSize: 10
+    pageSize: 10,
+    vipLevel: '',
+    paymentStatus: '1',
+    vipEnable: ''
   },
   rules: {}
 });
 
-const { queryParams, form, rules } = toRefs(data);
-const { form: approvalForm, rules: approvalRules } = toRefs(approvalData);
-
-/**动态显示审批理由 */
-const showRefuse = (res: any) => {
-  if (res == '2') {
-    refuseShow.value = true;
-    return;
-  }
-  refuseShow.value = false;
-};
-
+const { queryParams, form } = toRefs(data);
 /** 查询会员信息列表 */
 const getList = async () => {
   loading.value = true;
@@ -323,18 +157,6 @@ const getMemberLevelList = async () => {
   loading.value = false;
 };
 
-/** 取消按钮 */
-const cancel = () => {
-  reset();
-  dialog.visible = false;
-};
-
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  memberFormRef.value?.resetFields();
-};
-
 /** 搜索按钮操作 */
 const handleQuery = (level?: any) => {
   queryParams.value.pageNum = 1;
@@ -347,127 +169,37 @@ const handleQuery = (level?: any) => {
 /** 重置按钮操作 */
 const resetQuery = () => {
   queryFormRef.value?.resetFields();
+  queryParams.value.payStartDate = '';
+  queryParams.value.payEndDate = '';
   handleQuery();
 };
 
-/**审批弹框 */
-const showApp = (row: any) => {
-  approvalReset();
-  dialogApproval.visible = true;
-  approvalForm.value.id = row.id;
-  getMemberInfo(row.id);
-};
-
-/** 修改按钮操作 */
-const getMemberInfo = async (memberId: string) => {
-  reset();
-  const res = await getMember(memberId);
-  Object.assign(form.value, res.data);
-};
-
 const memberDetail = (row: any) => {
   router.push({ path: `/szyy/member-detail`, query: { memberId: row.id } });
 };
-
-/** 处理日期范围变化 */
-const handleDateRangeChange = (value: [string, string]) => {
-  if (value && value.length === 2) {
-    queryParams.value.startDate = value[0];
-    queryParams.value.endDate = value[1];
-  } else {
-    queryParams.value.startDate = undefined;
-    queryParams.value.endDate = undefined;
-  }
-  handleQuery();
-};
-
-/** 审批表单重置 */
-const approvalReset = () => {
-  refuseShow.value = false;
-  approvalForm.value = { ...initFormApprovalData };
-  approvalLogFormRef.value?.resetFields();
-};
-
-/** 多选框选中数据 */
-const handleSelectionChange = (selection: MemberVO[]) => {
-  ids.value = selection.map((item) => item.id);
-  single.value = selection.length != 1;
-  multiple.value = !selection.length;
-};
-
-/** 新增按钮操作 */
-const handleAdd = () => {
-  reset();
-  dialog.visible = true;
-  dialog.title = '添加会员信息';
-};
-
-/** 修改按钮操作 */
-const handleUpdate = async (row?: MemberVO) => {
-  reset();
-  const _id = row?.id || ids.value[0];
-  const res = await getMember(_id);
-  Object.assign(form.value, res.data);
-  dialog.visible = true;
-  dialog.title = '修改会员信息';
-};
-
-/** 提交按钮 */
-const submitForm = () => {
-  memberFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      buttonLoading.value = true;
-      if (form.value.id) {
-        await updateMember(form.value).finally(() => (buttonLoading.value = false));
-      } else {
-        await addMember(form.value).finally(() => (buttonLoading.value = false));
+const deleteItem = async (row: any) => {
+  console.log(row);
+  ElMessageBox({
+    title: '删除提示',
+    cancelButtonText: '取消',
+    confirmButtonText: '确认删除',
+    showCancelButton: true,
+    confirmButtonClass: 'el-button--danger',
+    message: h('p', null, [
+      h('div', null, `确认要删除企业:${row.cpyName} 吗?`),
+      h('div', null, [h('span', null, '注意:'), h('span', { style: 'color: #F56C6C' }, '删除后,该企业将不再是协会的会员单位,请谨慎操作!')])
+    ]),
+    callback: async (action: string) => {
+      if (action === 'confirm') {
+        const res = await delMember(row.id);
+        if (res) {
+          ElMessage.success('删除成功');
+          getList();
+        }
       }
-      proxy?.$modal.msgSuccess('修改成功');
-      dialog.visible = false;
-      await getList();
     }
   });
 };
-
-/**取消审批弹框 */
-const cancelApp = () => {
-  approvalReset();
-  dialogApproval.visible = false;
-};
-
-/**审批弹框 */
-const confirmApp = () => {
-  approvalLogFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      buttonLoading.value = true;
-      await approvalMember(approvalForm.value).finally(() => (buttonLoading.value = false));
-      proxy?.$modal.msgSuccess('操作成功');
-      dialogApproval.visible = false;
-      getList();
-    }
-  });
-};
-
-/** 删除按钮操作 */
-const handleDelete = async (row?: MemberVO) => {
-  const _ids = row?.id || ids.value;
-  await proxy?.$modal.confirm('是否确认删除会员信息编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
-  await delMember(_ids);
-  proxy?.$modal.msgSuccess('删除成功');
-  await getList();
-};
-
-/** 导出按钮操作 */
-const handleExport = () => {
-  proxy?.download(
-    'dgtmedicine/member/export',
-    {
-      ...queryParams.value
-    },
-    `member_${new Date().getTime()}.xlsx`
-  );
-};
-
 onMounted(() => {
   getList();
   getMemberLevelList();

+ 2 - 0
src/views/dgtmedicine/model/index.ts

@@ -0,0 +1,2 @@
+// 上传发票组件
+export { default as uploadInvoiceForm } from './uploadInvoiceForm.vue'; // 上传发票

+ 64 - 0
src/views/dgtmedicine/model/uploadInvoiceForm.vue

@@ -0,0 +1,64 @@
+<template>
+    <vxe-modal v-model="dialogVisible" :title="title" show-zoom resize show-footer destroy-on-close transfer @hide="close" :width="width">
+        <template #default>
+            <el-form ref="formRef" :model="form" :rules="rules" label-width="auto" hide-required-asterisk>
+                <el-form-item label="发票:" prop="invoiceUrl">
+                    <file-upload v-model="form.invoiceUrl" :limit="1" :isString="true" :fileType="['pdf']"/>
+                </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="EditLine" lang="ts">
+import { uploadInvoice } from '@/api/dgtmedicine/vipPayment/index';
+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),
+    info: propTypes.any.def(null),
+    lineId: propTypes.string.def(''),
+    dict: propTypes.any.def({}),
+});
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const dialogVisible = ref(false);
+const form = ref<any>({
+    invoiceUrl: ''
+});
+const rules = reactive({
+    invoiceUrl: [{ 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 res = await uploadInvoice({ ...form.value, id: props.info?.id });
+        if (res) {
+            close();
+            emit('success', true);
+        }
+    } catch (error) {
+        console.error(error);
+    }
+};
+
+watch(
+    () => props.show,
+    (val) => {
+        dialogVisible.value = val;
+    },
+    { immediate: true }
+);
+</script>

+ 28 - 290
src/views/dgtmedicine/pay-log/index.vue

@@ -4,27 +4,18 @@
       <div class="pd-16 border-bottom">
         <div class="f-s-20 c-333 f-w-7 mb-10">会费缴纳记录</div>
         <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="auto">
-          <el-form-item label="订单号" prop="cpyName">
-            <el-input v-model="queryParams.cpyName" placeholder="请输入订单号搜索" clearable style="width: 180px" @keyup.enter="handleQuery" />
+          <el-form-item label="订单号" prop="id">
+            <el-input v-model="queryParams.id" placeholder="请输入订单号搜索" clearable style="width: 180px" @keyup.enter="handleQuery" />
           </el-form-item>
           <el-form-item label="会员名称" prop="cpyName">
             <el-input v-model="queryParams.cpyName" placeholder="搜会员名称关键字" clearable style="width: 180px" @keyup.enter="handleQuery" />
           </el-form-item>
           <el-form-item label="缴费时间段" prop="dateRange">
-            <el-date-picker
-              style="width: 200px"
-              clearable
-              v-model="queryParams.dateRange"
-              type="daterange"
-              range-separator="至"
-              start-placeholder="开始日期"
-              end-placeholder="结束日期"
-              value-format="YYYY-MM-DD"
-              @change="handleDateRangeChange"
-            />
+            <DateRange v-model="queryParams.dateRange" v-model:start-date="queryParams.startDate"
+                v-model:end-date="queryParams.endDate" @change="handleQuery"></DateRange>
           </el-form-item>
           <el-form-item label="是否已开发票" prop="cpyName">
-            <el-select style="width: 140px" v-model="queryParams.invoiceStatus" clearable placeholder="搜有效期状态">
+            <el-select style="width: 140px" v-model="queryParams.invoiceStatus" clearable placeholder="搜有效期状态" @change="handleQuery">
               <el-option label="全部" value=""></el-option>
               <el-option label="已开票" value="1"></el-option>
               <el-option label="待开票" value="0"></el-option>
@@ -36,21 +27,10 @@
           </el-form-item>
         </el-form>
       </div>
-
-      <!-- <template #header>
-          <el-row :gutter="20" class="mb8">
-            <el-col :span="2" v-for="level in memberLevelCountList" :key="level.type">
-              <el-button type="text" @click="handleQuery(level)"
-                :style="{ fontWeight: queryParams.vipLevel === level.type ? 'bold' : 'normal', color: queryParams.vipLevel === level.type ? 'black' : 'inherit' }">{{
-                  level.name }}({{ level.num }})</el-button>
-            </el-col>
-            <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
-          </el-row>
-        </template> -->
       <div class="d-flex flex1 ov-hd flex-cln pd-16">
         <div class="flex1 ov-hd">
           <vxe-table :loading="loading" border :data="list" min-height="0" max-height="100%">
-            <vxe-column title="订单号" field="cpyName" min-width="100" :formatter="colNoData" />
+            <vxe-column title="订单号" field="id" min-width="100" :formatter="colNoData" />
             <vxe-column title="会员名称" field="cpyName" min-width="100" :formatter="colNoData" />
             <vxe-column title="会员级别" field="vipLevelDesc" width="100" :formatter="colNoData" />
             <vxe-column title="缴费金额" width="120" :formatter="colNoData">
@@ -63,9 +43,9 @@
               <template #default="{ row }"> {{ +row.invoiceStatus ? '已开票' : '待开票' }} </template>
             </vxe-column>
             <vxe-column title="操作" class-name="small-padding fixed-width">
-              <template #default="scope">
-                <el-button link type="primary" @click="showApp(scope.row)" v-if="scope.row.reviewStatus == '0'">审批</el-button>
-                <el-button link type="primary" @click="memberDetail(scope.row)" v-if="scope.row.reviewStatus != '0'">详情</el-button>
+              <template #default="{ row }">
+                <el-button v-if="+row.invoiceStatus" style="color: #999;"  tag="a" text :underline="false" type="primary" :href="row.invoiceUrlAddr" target="_blank">查看发票</el-button>
+                <el-button v-else type="primary" text @click="clickRowEdit(row)">上传发票</el-button>
               </template>
             </vxe-column>
           </vxe-table>
@@ -74,222 +54,39 @@
       </div>
     </div>
 
-    <!--审核弹窗-->
-    <el-dialog :close-on-click-modal="false" :title="dialogApproval.title" v-model="dialogApproval.visible" width="1200px" append-to-body>
-      <el-form ref="memberFormRef" :model="form" :rules="rules">
-        <el-row :gutter="20">
-          <el-col :span="8">
-            <el-form-item label="企业名称" prop="cpyName">
-              <el-text v-model="form.cpyName">{{ form.cpyName }}</el-text>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="法人姓名" prop="legalPersonName">
-              <el-text>{{ form.legalPersonName }}</el-text>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="法人电话" prop="legalPersonPhone">
-              <el-text>{{ form.legalPersonPhone }}</el-text>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
-          <el-col :span="8">
-            <el-form-item label="法人职务" prop="legalPersonPosition">
-              <el-text>{{ form.legalPersonPosition }}</el-text>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="法人身份证正面图片" prop="legalPersonIdFront">
-              <el-image
-                :src="form.legalPersonIdFront"
-                style="width: 100px; height: 100px"
-                show-progress
-                :preview-src-list="[form.legalPersonIdFront]"
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="法人身份证背面图片" prop="legalPersonIdBack">
-              <el-image
-                :src="form.legalPersonIdBack"
-                style="width: 100px; height: 100px"
-                show-progress
-                :preview-src-list="[form.legalPersonIdBack]"
-              />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
-          <el-col :span="8">
-            <el-form-item label="申请会员等级" prop="applyLevel">
-              <dict-tag :value="form.applyLevel" :options="vip_level" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="邮箱" prop="email">
-              <el-text>{{ form.email }}</el-text>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="主管部门" prop="department">
-              <el-text>{{ form.department }}</el-text>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
-          <el-col :span="8">
-            <el-form-item label="总资产" prop="totalAssets">
-              <el-text>{{ form.totalAssets }}</el-text>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="单位简介" prop="introduction">
-              <el-text>{{ form.introduction }}</el-text>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="入会目的" prop="membershipPurpose">
-              <el-text>{{ form.membershipPurpose }}</el-text>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="20">
-          <el-col :span="8">
-            <el-form-item label="当前会员等级" prop="vipLevel">
-              <dict-tag :value="form.vipLevel" :options="vip_level" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="开始时间" prop="startDate">
-              <el-text>{{ form.startDate }}</el-text>
-            </el-form-item>
-          </el-col>
-          <el-col :span="8">
-            <el-form-item label="结束时间" prop="endDate">
-              <el-text>{{ form.endDate }}</el-text>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-table v-loading="loading" :data="form.plantingInfo">
-          <vxe-column label="品种名称" align="center" prop="variety" />
-          <vxe-column label="种植面积" align="center" prop="plantingArea" />
-          <vxe-column label="种植地点" align="center" prop="plantingPlace" />
-        </el-table>
-        <el-row :gutter="20">
-          <el-col>
-            <el-form-item label="荣誉证书" prop="companyCertificate">
-              <el-image
-                :src="form.companyCertificate"
-                style="width: 100px; height: 100px"
-                show-progress
-                :preview-src-list="form.companyCertificate"
-              />
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-      <el-form ref="approvalLogFormRef" :model="approvalForm" :rules="approvalRules" label-width="80px">
-        <el-form-item label="审批类型" prop="reviewStatus">
-          <el-select v-model="approvalForm.reviewStatus" placeholder="请选择" clearable style="width: 100%" @change="showRefuse">
-            <template v-for="dict in cpy_res_status">
-              <el-option v-if="dict.value != '0'" :key="dict.value" :label="dict.label" :value="dict.value" />
-            </template>
-          </el-select>
-        </el-form-item>
-        <el-form-item label="审批理由" prop="msg" v-if="refuseShow">
-          <el-input type="textarea" v-model="approvalForm.reviewMsg" placeholder="请输入拒绝理由" />
-        </el-form-item>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button :loading="buttonLoading" type="primary" @click="confirmApp">确 定</el-button>
-          <el-button @click="cancelApp">取 消</el-button>
-        </div>
-      </template>
-    </el-dialog>
   </div>
+  <uploadInvoiceForm v-if="showInvoice" v-model:show="showInvoice" :info="rowInfo"></uploadInvoiceForm>
 </template>
-<script setup name="Member" lang="ts">
-import { getMember, countLevelMember } from '@/api/dgtmedicine/member/index';
-import { approvalMember } from '@/api/dgtmedicine/approvalLog/index';
-import { MemberLevelCountVO } from '@/api/dgtmedicine/member/types';
-import { ApprovalLogQuery, ApprovalLogForm } from '@/api/dgtmedicine/approvalLog/types';
+<script setup name="Pay-log" lang="ts">
 import { colNoData } from '@/utils/noData';
 import { listVipPayment } from '@/api/dgtmedicine/vipPayment/index';
+import { DateRange } from '@/views/models/index';
+import { uploadInvoiceForm } from '../model/index';
 const router = useRouter();
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-const { cpy_res_status, vip_level } = toRefs<any>(proxy?.useDict('cpy_res_status', 'vip_level'));
 const list = ref<any[]>([]);
-const memberLevelCountList = ref<MemberLevelCountVO[]>([]);
-const buttonLoading = ref(false);
 const loading = ref(true);
 const showSearch = ref(true);
-const refuseShow = ref(false);
-const ids = ref<Array<string | number>>([]);
-const single = ref(true);
-const multiple = ref(true);
+const showInvoice = ref(false);
 const total = ref(0);
-const approvalLogFormRef = ref<ElFormInstance>();
-
 const queryFormRef = ref<ElFormInstance>();
-const memberFormRef = ref<ElFormInstance>();
-
-const dialog = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const initFormApprovalData: ApprovalLogForm = {
-  id: undefined,
-  targetType: undefined,
-  reviewStatus: '1',
-  reviewMsg: undefined
-};
-
-const dialogApproval = reactive<DialogOption>({
-  visible: false,
-  title: ''
-});
-
-const approvalData = reactive<any>({
-  form: { ...initFormApprovalData },
-  queryParams: {
-    pageNum: 1,
-    pageSize: 10,
-    targetType: undefined,
-    targetId: undefined,
-    res: undefined,
-    msg: undefined,
-    params: {}
-  },
-  rules: {}
-});
-
-const initFormData: any = {};
 const data = reactive<any>({
-  form: { ...initFormData },
   queryParams: {
     pageNum: 1,
-    pageSize: 10
-  },
-  rules: {}
-});
-
-const { queryParams, form, rules } = toRefs(data);
-const { form: approvalForm, rules: approvalRules } = toRefs(approvalData);
-
-/**动态显示审批理由 */
-const showRefuse = (res: any) => {
-  if (res == '2') {
-    refuseShow.value = true;
-    return;
+    pageSize: 10,
+    dateRange: [],
+    id: '',
+    startDate: '',
+    endDate: '',
   }
-  refuseShow.value = false;
+});
+const { queryParams } = toRefs(data);
+/** 点击行上传发票 */
+const rowInfo = ref<any>({});
+const clickRowEdit = (row: any) => {
+  rowInfo.value = row;
+  showInvoice.value = true;
 };
-
 /** 查询会员信息列表 */
 const getList = async () => {
   loading.value = true;
@@ -299,12 +96,6 @@ const getList = async () => {
   loading.value = false;
 };
 
-/** 表单重置 */
-const reset = () => {
-  form.value = { ...initFormData };
-  memberFormRef.value?.resetFields();
-};
-
 /** 搜索按钮操作 */
 const handleQuery = (level?: any) => {
   queryParams.value.pageNum = 1;
@@ -317,64 +108,11 @@ const handleQuery = (level?: any) => {
 /** 重置按钮操作 */
 const resetQuery = () => {
   queryFormRef.value?.resetFields();
+  queryParams.value.startDate = '';
+  queryParams.value.endDate = '';
   handleQuery();
 };
 
-/**审批弹框 */
-const showApp = (row: any) => {
-  approvalReset();
-  dialogApproval.visible = true;
-  approvalForm.value.id = row.id;
-  getMemberInfo(row.id);
-};
-
-/** 修改按钮操作 */
-const getMemberInfo = async (memberId: string) => {
-  reset();
-  const res = await getMember(memberId);
-  Object.assign(form.value, res.data);
-};
-
-const memberDetail = (row: any) => {
-  router.push({ path: `/szyy/member-detail`, query: { memberId: row.id } });
-};
-
-/** 处理日期范围变化 */
-const handleDateRangeChange = (value: [string, string]) => {
-  if (value && value.length === 2) {
-    queryParams.value.startDate = value[0];
-    queryParams.value.endDate = value[1];
-  } else {
-    queryParams.value.startDate = undefined;
-    queryParams.value.endDate = undefined;
-  }
-  handleQuery();
-};
-
-/** 审批表单重置 */
-const approvalReset = () => {
-  refuseShow.value = false;
-  approvalForm.value = { ...initFormApprovalData };
-  approvalLogFormRef.value?.resetFields();
-};
-/**取消审批弹框 */
-const cancelApp = () => {
-  approvalReset();
-  dialogApproval.visible = false;
-};
-
-/**审批弹框 */
-const confirmApp = () => {
-  approvalLogFormRef.value?.validate(async (valid: boolean) => {
-    if (valid) {
-      buttonLoading.value = true;
-      await approvalMember(approvalForm.value).finally(() => (buttonLoading.value = false));
-      proxy?.$modal.msgSuccess('操作成功');
-      dialogApproval.visible = false;
-      getList();
-    }
-  });
-};
 
 onMounted(() => {
   getList();

+ 59 - 0
src/views/models/BtnRadio.vue

@@ -0,0 +1,59 @@
+<template>
+    <div class="btn-radio-wrap d-flex f-w-w">
+        <template v-for="item in options" :key="item.value">
+            <div class="btn-radio-item" @click="change(item.value)" :class="{ checked: item.value === activeName }">
+                <template v-if="isNum"> {{ item.label }}({{ item.count }}) </template>
+                <template v-else> {{ item.label }} </template>
+            </div>
+        </template>
+    </div>
+</template>
+<script setup name="searchTabs" lang="ts">
+import { propTypes } from '@/utils/propTypes';
+const emit = defineEmits(['update:modelValue', 'change']);
+const activeName = ref('');
+const props = defineProps({
+    modelValue: propTypes.string.def(''),
+    options: propTypes.any.def([]),
+    isNum: propTypes.bool.def(false)
+});
+const change = (event: any) => {
+    activeName.value = event;
+    emit('update:modelValue', event);
+    emit('change', event);
+};
+watch(
+    () => props.modelValue,
+    async (val) => {
+        if (val) {
+            activeName.value = val as string;
+        }
+    },
+    { deep: true, immediate: true }
+);
+</script>
+<style lang="scss" scoped>
+.btn-radio-wrap {
+
+    .btn-radio-item {
+        box-sizing: border-box;
+        padding: 0 20px;
+        height: 40px;
+        line-height: 38px;
+        color: #333;
+        font-size: 14px;
+        border: 1px solid var(--base-radio-border-color);
+        border-radius: 4px;
+        margin: 0 20px 20px 0;
+        cursor: pointer;
+        user-select: none;
+
+        &.checked {
+            background-color: var(--el-color-primary);
+            color: #fff;
+            border-color: var(--el-color-primary);
+        }
+    }
+   
+}
+</style>

+ 37 - 0
src/views/models/DateRange.vue

@@ -0,0 +1,37 @@
+<template>
+    <el-date-picker
+        v-model="dateTime"
+        clearable
+        type="daterange"
+        class="flex1"
+        value-format="YYYY-MM-DD"
+        range-separator="至"
+        start-placeholder="开始时间"
+        end-placeholder="结束时间"
+        @change="changeDate"
+    />
+</template>
+
+<script setup name="DateRange" lang="ts">
+import { propTypes } from '@/utils/propTypes';
+const emit = defineEmits(['update:startDate', 'update:endDate', 'update:modelValue', 'change']);
+const dateTime = ref<string[]>([])
+const props = defineProps({
+   modelValue: propTypes.any.def([]),
+   startDate: propTypes.string.def(''),
+   endDate: propTypes.string.def(''),
+});
+const changeDate = (val: string[]) => {
+    emit('update:modelValue', val)
+    emit('update:startDate', val?.[0])
+    emit('update:endDate', val?.[1])
+    emit('change', val)
+}
+watch(() => props.modelValue, (val) => {
+    dateTime.value = val
+    if (!val?.length) {
+        emit('update:startDate', '')
+        emit('update:endDate', '')
+    }
+})
+</script>

+ 32 - 0
src/views/models/DescCol.vue

@@ -0,0 +1,32 @@
+<template>
+    <el-col :span="span" :md="md" :lg="lg" :xl="xl">
+        <div class="desc-col f-14" :class="className">
+            <slot name="label">{{ label }}{{ mh }}</slot>
+            <span class="c-333"><slot></slot></span>
+        </div>
+    </el-col>
+</template>
+
+<script setup name="DescCol" lang="ts">
+import { propTypes } from '@/utils/propTypes';
+
+const props = defineProps({
+    span: propTypes.number.def(6),
+    md: propTypes.number.def(24),
+    lg: propTypes.number.def(8),
+    xl: propTypes.number.def(6),
+    label: String,
+    isSv: Boolean,
+    size: propTypes.number.def(16),
+    className: propTypes.string.def(''),
+    mh: propTypes.string.def(':'),
+});
+</script>
+<style lang="scss" scoped>
+.desc-col {
+    padding: 2px 0;
+    line-height: 1.8;
+    color: rgba(102, 102, 102, 1);
+    word-break: break-all;
+}
+</style>

+ 5 - 0
src/views/models/index.ts

@@ -0,0 +1,5 @@
+
+export { default as DateRange } from './DateRange.vue'; // 包装任务
+export { default as searchTabs } from './searchTabs.vue'; // tabs组件
+export { default as DescCol } from './DescCol.vue'; // 描述组件
+export { default as BtnRadio } from './BtnRadio.vue'; // 按钮单选

+ 57 - 0
src/views/models/searchTabs.vue

@@ -0,0 +1,57 @@
+<template>
+  <div class="ridio-info d-flex f-w-w">
+    <!-- <div class="ridio-item f-12" @click="change('')" :class="{ checked: !activeName }">全部({{ total }})</div> -->
+    <template v-for="item in list" :key="item.value">
+      <div class="ridio-item f-s-12 f-w-5" @click="change(item[keyValue])" :class="{ checked: (item[keyValue] || '') === activeName }">
+        <template v-if="isNum"> {{ item[keyLabel] }}({{ item[keyCount] }}) </template>
+        <template v-else> {{ item[keyLabel] }} </template>
+      </div>
+    </template>
+  </div>
+</template>
+<script setup name="searchTabs" lang="ts">
+import { propTypes } from '@/utils/propTypes';
+const emit = defineEmits(['update:modelValue', 'change']);
+const activeName = ref('');
+const props = defineProps({
+  modelValue: propTypes.string.def(''),
+  list: propTypes.any.def([]),
+  isNum: propTypes.bool.def(true),
+  keyLabel: propTypes.string.def('label'),
+  keyCount: propTypes.string.def('count'),
+  keyValue: propTypes.string.def('value')
+});
+const change = (event: any) => {
+  activeName.value = event || '';
+  emit('update:modelValue', event);
+  emit('change', event);
+};
+watch(
+  () => props.modelValue,
+  async (val) => {
+    if (val) {
+      activeName.value = val as string;
+    }
+  },
+  { deep: true, immediate: true }
+);
+</script>
+<style lang="scss" scoped>
+.ridio-info {
+  margin-left: -10px;
+  .ridio-item {
+    margin: 5px;
+    padding: 8px 10px;
+    line-height: 1.2;
+    border-radius: 15px;
+    user-select: none;
+    background-color: #f1f1f2;
+    cursor: pointer;
+
+    &.checked {
+      color: var(--el-color-primary);
+      background-color: var(--el-color-primary-light-9);
+    }
+  }
+}
+</style>

+ 3 - 1
vite.config.ts

@@ -25,7 +25,9 @@ export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => {
       open: true,
       proxy: {
         [env.VITE_APP_BASE_API]: {
-          target: 'http://dm.yujin.shuziyunyao.com/api',
+          // target: 'http://dm.yujin.shuziyunyao.com/api',
+          // 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), '')