lisy vor 4 Monaten
Ursprung
Commit
db1c42a667

+ 40 - 1
src/api/training/index.ts

@@ -116,7 +116,7 @@ export const editPrice = (data: any): AxiosPromise => {
     });
 };
 // 开关会议临时状态
-export const confirmSigPublicPay = (id: any,payType:any): AxiosPromise => {
+export const confirmSigPublicPay = (id: any, payType:any): AxiosPromise => {
     return request({
         url: `/dgtmedicine/trainingSignup/confirmSigPublicPay/${id}?payType=${payType}`,
         method: 'get'
@@ -138,3 +138,42 @@ export const switchPage = (params: any): AxiosPromise => {
         params
     });
 };
+// 导入会议特殊人员收费列表
+export const importFeeList = (data: any): AxiosPromise => {
+    return request({
+        url: `/dgtmedicine/training/importFeeList`,
+        method: 'post',
+        data
+    });
+};
+// 查询培训特殊人员收费列表
+export const trainingfee = (params: any): AxiosPromise => {
+    return request({
+        url: `/dgtmedicine/trainingfee/list`,
+        method: 'get',
+        params
+    });
+};
+// 清空会议特殊人员收费列表
+export const clearFeeList = (id: any): AxiosPromise => {
+    return request({
+        url: `/dgtmedicine/training/clearFeeList/${id}`,
+        method: 'get'
+    });
+};
+//报名信息标注
+export const markTags = (data: any): AxiosPromise => {
+    return request({
+        url: `/dgtmedicine/trainingSignup/markTags`,
+        method: 'post',
+        data
+    });
+};
+//修改指定联系人
+export const signupContact = (data: any): AxiosPromise => {
+    return request({
+        url: `/dgtmedicine/trainingSignup/signupContact`,
+        method: 'post',
+        data
+    });
+};

+ 3 - 2
src/views/training/meeting-detail/index.vue

@@ -19,6 +19,7 @@
             </div>
             <MeetingDetailAttend v-if="activeName === '1'" :form="form" />
             <MeetingDetailInfo v-if="activeName === '2'" :form="form" />
+            <meetingSpecialList v-if="activeName === '3'" :form="form" />
         </div>
     </div>
 </template>
@@ -27,7 +28,7 @@
 import { trainingDetailById, trainingMembers } from '@/api/training';
 import router from '@/router';
 import { onMounted, ref } from 'vue';
-import { MeetingDetailInfo } from '../models';
+import { MeetingDetailInfo,meetingSpecialList } from '../models';
 import MeetingDetailAttend from '../models/meeting-detail-attend.vue';
 
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -36,7 +37,7 @@ const { lm_training_join_type, yes_no, dm_training_cert, lm_training_status, lm_
 const tabs = ref([
     { label: '参会人员信息', value: '1' },
     { label: '会议信息', value: '2' },
-
+    {label: '特殊清单', value: '3'}
 ])
 
 const activeName = ref('1');

+ 1 - 0
src/views/training/models/index.ts

@@ -9,3 +9,4 @@ export { default as MeetingTplH5 } from './meeting-tpl-h5.vue';
 export { default as MeetingTplList } from './meeting-tpl-list.vue';
 export { default as MeetingTplEvents } from './meeting-tpl-events.vue';
 export { default as SelectMeetingTplPage } from './select-meeting-tpl-page.vue';
+export { default as meetingSpecialList } from './meeting-special-list.vue';

+ 91 - 8
src/views/training/models/meeting-detail-attend.vue

@@ -96,22 +96,22 @@
                         <el-option v-for="item in temp_join_type" :key="item.value" :label="item.label" :value="item.value" />
                     </el-select>
                 </el-form-item>
-                <el-form-item label="审核状态:" prop="tempJoin">
+                <el-form-item label="审核状态:" prop="res">
                     <el-select v-model="queryParams.res" placeholder="请选择审核状态" clearable style="width: 180px">
                         <el-option v-for="item in cpy_res_status" :key="item.value" :label="item.label" :value="item.value" />
                     </el-select>
                 </el-form-item>
-                <el-form-item label="支付状态:" prop="tempJoin">
+                <el-form-item label="支付状态:" prop="payStatus">
                     <el-select v-model="queryParams.payStatus" placeholder="请选择支付状态" clearable style="width: 180px">
                         <el-option v-for="item in dm_pay_status" :key="item.value" :label="item.label" :value="item.value" />
                     </el-select>
                 </el-form-item>
-                <el-form-item label="支付方式:" prop="tempJoin">
+                <el-form-item label="支付方式:" prop="payType">
                     <el-select v-model="queryParams.payType" placeholder="请选择支付方式" clearable style="width: 180px">
                         <el-option v-for="item in [{value:'1',label:'微信支付'},{value:'2',label:'对公转账'}]" :key="item.value" :label="item.label" :value="item.value" />
                     </el-select>
                 </el-form-item>
-                <el-form-item label="是否需要开票:" prop="tempJoin">
+                <el-form-item label="是否需要开票:" prop="hasInvoice">
                     <el-select v-model="queryParams.hasInvoice" placeholder="请选择" clearable style="width: 180px">
                         <el-option v-for="item in [{value:'0',label:'不需要'},{value:'1',label:'需要'}]" :key="item.value" :label="item.label" :value="item.value" />
                     </el-select>
@@ -138,7 +138,12 @@
                     </div>
                 </template>
             </vxe-column>
-            <vxe-column title="姓名" field="name" min-width="100" :formatter="colNoData" />
+            <vxe-column title="姓名" field="name" min-width="100" :formatter="colNoData">
+                <template #default="{ row }">
+                    <div class="f-w-5">{{ row?.name }}</div>
+                    <div class="f-w-5">{{ row?.extendInfo?.tags }}</div>
+                </template>
+            </vxe-column>
             <!-- <vxe-column title="职务" field="position" min-width="100" :formatter="colNoData" /> -->
             <vxe-column title="联系方式" field="contact" min-width="100" :formatter="colNoData" />
             <vxe-column title="备注" field="remark" min-width="100" :formatter="colNoData" />
@@ -215,6 +220,9 @@
                     <el-upload v-if="form?.trainingStatus == '2' && +row.joinFee && +row?.hasInvoice && +row?.invoiceStatus && row.payStatus == '1' &&form?.meetingCharge?.hasFee =='1'&& row?.res !== '0' && row?.res !== '2'" class="upload-demo" :action="uploadFileUrl" multiple :limit="1" :on-success="handleSuccess" :headers="headers" :show-file-list="false" accept=".pdf,.PDF">
                         <el-button type="primary" color="#33aeeb" style="color: white" @click=" invoiceId = row.id">重新上传</el-button>
                     </el-upload>
+                    <el-button @click="openPersonnelLabel(row?.id)">设置人员标签</el-button>
+                    <el-button @click="opencontactPerson(row?.id,row)" v-if="!+row?.extendInfo?.contactInfo?.specifyConcatTel">设置联系人</el-button>
+                    <el-button @click="opencontactPerson(row?.id,row)" v-else>查看联系人</el-button>
                 </template>
             </vxe-column>
         </vxe-table>
@@ -303,10 +311,49 @@
             <div>{{ invoiceData?.bankAccount || '-'}}</div>
         </div>
     </el-dialog>
+    <el-dialog v-model="personnelLabel" title="设置人员标签" width="600" center>
+        <el-checkbox-group v-model="radioLabel">
+            <el-checkbox v-for="(item,index) in signup_tags_type" :key="index" :label="item?.label" :value="item.value" />
+        </el-checkbox-group>
+        <template #footer>
+            <div class="dialog-footer">
+                <el-button @click="personnelLabel = false">取消</el-button>
+                <el-button type="primary" @click="confirmPersonnelLabel()">确认添加</el-button>
+            </div>
+        </template>
+    </el-dialog>
+    <el-dialog v-model="contactPerson" title="设置1对1联系人" width="600" center>
+        <template #header="{titleId }">
+            <div class="my-header">
+                <div :id="titleId" class="f-s-20">为{{contactData?.name}}({{ contactData?.contact}})设置1对1联系人</div>
+            </div>
+        </template>
+        <el-form :model="contactPersonData">
+            <el-form-item prop="contactName" :rules="[{ required: true, message: '请填写指定联系人名称' }]">
+                <div class="d-flex a-c">
+                    <div class="pr-20">指定联系人名称</div>
+                    <el-input v-model="contactPersonData.contactName" style="width: 300px;"></el-input>
+                </div>
+            </el-form-item>
+            <el-form-item prop="contactTel" :rules="[{ required: true, message: '请填写指定联系人电话' }]">
+                <div class="d-flex pt-20 a-c">
+                    <div class="pr-20">指定联系人电话</div>
+                    <el-input v-model.number="contactPersonData.contactTel" style="width: 300px;"></el-input>
+                </div>
+            </el-form-item>
+        </el-form>
+        <template #footer>
+            <div class="dialog-footer">
+                <el-button @click="contactPerson = false">取消</el-button>
+                <el-button type="primary" @click="confirmContactPerson()" v-if="!+contactData?.extendInfo?.contactInfo?.specifyConcatTel">确认添加</el-button>
+                <el-button type="primary" @click="confirmContactPerson()" v-else>确认修改</el-button>
+            </div>
+        </template>
+    </el-dialog>
     <registrationInfo v-if="showTemporary" v-model:show="showTemporary" :info="temporaryRegistration"></registrationInfo>
 </template>
 <script setup name="MeetingDetailInfo" lang="ts">
-import { exportTrainingMembers, signupApproval, signupCount, trainingMembers,editPrice,confirmSigPublicPay,uploadInvoice} from '@/api/training';
+import { exportTrainingMembers, signupApproval, signupCount, trainingMembers,editPrice,confirmSigPublicPay,uploadInvoice,markTags,signupContact} from '@/api/training';
 import { colNoData } from '@/utils/noData';
 import { searchTabs } from '@/views/models';
 import { debounce } from 'lodash';
@@ -314,9 +361,8 @@ import { onMounted, reactive, ref ,ComponentPublicInstance} from 'vue';
 import registrationInfo from './registration-info.vue';
 import { AreaCascader } from '@/views/components';
 import { globalHeaders } from '@/utils/request';
-import { isWindow } from 'element-plus/es/utils';
 const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-const { cpy_res_status, lm_signup_status_app_show, dm_check_join_type,temp_join_type,dm_pay_status,lm_signup_status_app_query} = toRefs<any>(proxy?.useDict('cpy_res_status', 'lm_signup_status_app_show', 'dm_check_join_type','temp_join_type','dm_pay_status',"lm_signup_status_app_query"));
+const { cpy_res_status, lm_signup_status_app_show, dm_check_join_type,temp_join_type,dm_pay_status,lm_signup_status_app_query,signup_tags_type} = toRefs<any>(proxy?.useDict('cpy_res_status', 'lm_signup_status_app_show', 'dm_check_join_type','temp_join_type','dm_pay_status',"lm_signup_status_app_query","signup_tags_type"));
 // 获取详情
 const props = defineProps({
     form: {
@@ -353,6 +399,43 @@ const fromvalue = ref<any>({
     msg: ''
 })
 const collectiontype =ref()
+const personnelLabel = ref(false)
+const radioLabel = ref()
+const radioLabelId = ref()
+const contactPerson = ref(false)
+const contactId = ref()
+const contactData = ref()
+const contactPersonData = ref({
+    contactName:'',
+    contactTel:''
+})
+const openPersonnelLabel = (id)=>{
+    radioLabel.value = []
+    personnelLabel.value = true
+    radioLabelId.value = id
+}
+const confirmPersonnelLabel = async()=>{
+    personnelLabel.value = false
+    await markTags({id:radioLabelId.value,tags:radioLabel.value.join(',')})
+    radioLabel.value = []
+}
+const opencontactPerson = (id,data)=>{
+    contactId.value = id
+    contactData.value= data
+    contactPerson.value = true
+    if(data?.extendInfo?.contactInfo?.specifyContact && data?.extendInfo?.contactInfo?.specifyConcatTel){
+        contactPersonData.value.contactName = data.extendInfo.contactInfo.specifyContact
+        contactPersonData.value.contactTel = data.extendInfo.contactInfo.specifyConcatTel
+    }else{
+        contactPersonData.value.contactName = ''
+        contactPersonData.value.contactTel = ''
+    }
+
+}
+const confirmContactPerson = async()=>{
+    await signupContact({id:contactId.value,contactInfo:{specifyConcatTel:contactPersonData.value?.contactTel,specifyContact:contactPersonData.value?.contactName}})
+    contactPerson.value = false
+}
 const checkInvoiceData = (row)=>{
     invoicingInformation.value = true
     invoiceData.value = row

+ 236 - 0
src/views/training/models/meeting-special-list.vue

@@ -0,0 +1,236 @@
+<template>
+    <div class="pd-16" style="overflow: auto;">
+        <div class="d-flex f-s-26">配置后按配置金额收费</div>
+        <div class="d-flex j-st pt-20">
+            <!-- <div>
+                <searchTabs v-if="form?.conditions?.totalCheck == '1'" v-model="queryParams.res" @change="handleQuery" :list="tabs" key-label="name" key-count="num" key-value="type"></searchTabs>
+            </div> -->
+            <span style="width: 1px;"></span>
+            <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="auto">
+                <el-form-item label="手机号:" prop="phone">
+                    <el-input v-model="queryParams.phone" placeholder="请输入手机号" clearable style="width: 180px" />
+                </el-form-item>
+                <el-form-item label="姓名:" prop="name">
+                    <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>
+                    <el-button icon="Refresh" @click="resetQuery" class="mr-10">重置</el-button>
+                    <el-upload class="upload-demo" :action="uploadFileUrl" multiple :limit="1" :on-success="handleSuccess" :headers="headers" :show-file-list="false" accept=".xls,.xlsx">
+                        <el-button class="pl-10 mr-10">导入特殊清单</el-button>
+                    </el-upload>
+                    <el-button @click="dialogVisible = true">清空特殊清单</el-button>
+                </el-form-item>
+            </el-form>
+        </div>
+        <vxe-table v-if="form" :loading="loading" border :data="list" min-height="0">
+            <!-- 序号 -->
+            <vxe-column type="seq" width="60" title="序号" align="center" />
+            <vxe-column title="姓名" field="name" min-width="100" :formatter="colNoData" />
+            <!-- <vxe-column title="职务" field="position" min-width="100" :formatter="colNoData" /> -->
+            <vxe-column title="手机号" field="contact" min-width="100" :formatter="colNoData" />
+            <vxe-column title="参会费用" field="joinFee" min-width="100" :formatter="colNoData" v-if="form?.meetingCharge?.hasFee =='1'">
+                <template #default="{ row }">
+                    <div class="f-w-5">{{ row?.joinFee }}</div>
+                </template>
+            </vxe-column>
+        </vxe-table>
+        <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
+        <el-dialog v-model="dialogVisible" title="清空所有数据" width="500">
+            <span>确定清空所有数据吗?</span>
+            <template #footer>
+                <div class="dialog-footer">
+                    <el-button @click="dialogVisible = false">取消</el-button>
+                    <el-button type="primary" @click="clearData()">确认</el-button>
+                </div>
+            </template>
+        </el-dialog>
+    </div>
+</template>
+<script setup name="MeetingDetailInfo" lang="ts">
+import {trainingfee,importFeeList,clearFeeList} from '@/api/training';
+import { colNoData } from '@/utils/noData';
+import { searchTabs } from '@/views/models';
+import { debounce } from 'lodash';
+import { onMounted, reactive, ref ,ComponentPublicInstance} from 'vue';
+import registrationInfo from './registration-info.vue';
+import { AreaCascader } from '@/views/components';
+import { globalHeaders } from '@/utils/request';
+import { isWindow } from 'element-plus/es/utils';
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { cpy_res_status, lm_signup_status_app_show, dm_check_join_type,temp_join_type,dm_pay_status,lm_signup_status_app_query} = toRefs<any>(proxy?.useDict('cpy_res_status', 'lm_signup_status_app_show', 'dm_check_join_type','temp_join_type','dm_pay_status',"lm_signup_status_app_query"));
+// 获取详情
+const props = defineProps({
+    form: {
+        type: Object,
+        default: () => ({})
+    }
+});
+const baseUrl = import.meta.env.VITE_APP_BASE_API;
+const uploadFileUrl = ref(baseUrl + '/resource/oss/upload'); // 上传文件服务器地址
+const rules = reactive({
+    res: [
+        { required: true, message: '请选择审核结果', trigger: 'blur' }
+    ],
+    msgRequired: [ // For "不通过" (value="2")
+        { required: true, message: '请填写不通过的理由', trigger: 'blur' }
+    ],
+    msgOptional: [ // For "通过" (value="1")
+        { required: false, trigger: 'blur' }
+    ]
+})
+const headers = ref(globalHeaders());
+const fromvalue = ref<any>({
+    targetId: '',
+    msg: ''
+})
+
+const query = useRoute().query;
+
+const queryParams = ref<any>({
+    pageNum: 1,
+    pageSize: 10,
+    trainId: query?.id || '',
+    phone:'',
+});
+const loading = ref(false);
+const total = ref(0);
+const list = ref<any>([]);
+const tabs = ref([]);
+const formRef = ref()
+const dialogVisible = ref(false)
+const getList = async () => {
+    loading.value = true;
+    const res = await trainingfee(queryParams.value);
+    if (!res || res.code !== 200) return;
+    list.value = res.rows;
+    total.value = res.total;
+    loading.value = false;
+};
+
+const clearData = async()=>{
+    await clearFeeList(props.form.id)
+    dialogVisible.value = false
+    getList();
+}
+const handleQuery = () => {
+    queryParams.value.pageNum = 1;
+    getList();
+};
+const queryFormRef = ref<ElFormInstance>();
+const resetQuery = () => {
+    queryFormRef.value?.resetFields();
+    handleQuery();
+};
+
+const handleSuccess = async(res,uploadFile)=>{
+    await importFeeList({
+        trainingId:props.form.id,
+        xlsUrl:res.data.url
+    })
+    getList();
+}
+onMounted(() => {
+    getList();
+});
+</script>
+<style scoped lang="scss">
+.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;
+}
+
+.reject-radio :deep(.el-radio__label) {
+    color: #F56C6C;
+}
+.orange-radio :deep(.el-radio__label) {
+    color: orange;
+}
+.reject-radio :deep(.el-radio__inner) {
+    border-color: #F56C6C;
+    background: #F56C6C;
+}
+
+.reject-radio :deep(.el-radio__border) {
+    border-color: #F56C6C;
+}
+
+:deep(.reject-radio.el-radio.is-bordered.is-checked) {
+    border-color: #F56C6C !important;
+}
+.single{
+    position: absolute;
+    top: -20px;
+    right: 30px;
+    width: 200px;
+    left: 70px;
+}
+.orange-button{
+    border:1px solid #d7d7d7;
+    height: 100px;
+    width: 300px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+    font-size: 36px;
+    margin-right: 40px;
+    margin-bottom: 40px;
+    font-weight: 600;
+}
+.orange-button:hover{
+    color: white;
+    background-color: orange;
+    border: 1px solid orange;
+    opacity: 0.5;
+}
+.green-button:hover{
+    color: white;
+    background-color: green;
+    border: 1px solid green;
+    opacity: 0.5;
+}
+.green-button{
+    border:1px solid #d7d7d7;
+    height: 100px;
+    width: 300px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+    font-size: 36px;
+    margin-right: 40px;
+    margin-bottom: 40px;
+    font-weight: 600;
+}
+
+.orange-active{
+    color: white;
+    background-color: orange;
+    border: 1px solid orange;
+}
+.green-active{
+    color: white;
+    background-color: green;
+    border: 1px solid green;
+}
+.titleClass{
+    font-size: 30px !important;
+}
+</style>