Przeglądaj źródła

Merge branch 'master' of http://47.100.37.243:10191/wutt/manHourHousekeeper into master

seyason 11 miesięcy temu
rodzic
commit
536ef518d7
15 zmienionych plików z 639 dodań i 294 usunięć
  1. 3 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/api.ts
  2. 4 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/component/attachment.vue
  3. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/index.vue
  4. 1 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/api.ts
  5. 120 44
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/attachment.vue
  6. 3 3
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/deteleTables.vue
  7. 164 28
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/information.vue
  8. 13 33
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/operationRecord.vue
  9. 170 57
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/relatedBusiness.vue
  10. 1 43
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/relatedTasks.vue
  11. 8 9
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/detail/index.vue
  12. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/index.vue
  13. 59 21
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserWithBeisenController.java
  14. 65 47
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  15. 26 6
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

+ 3 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/api.ts

@@ -2,6 +2,9 @@ export const SENDVCODE = "/user/sendVcode";     //发送验证码
 export const REGISTER = "/user/insertCompany";  //注册
 export const LOGIN = "/user/loginAdmin";        //登录
 export const IMPORTTIMELIST = "/sys-form/getExportTemplate" // 下载模板
+export const URL_UPLOADFILE = `/contacts-document/fileUpload` // 上传文件
+export const URLFILEDETELE = `/contacts-document/fileDelete` // 删除文件
+export const URL_REFNAME = `/contacts-document/reNameFile` // 文件重命名
 
 export const SEX: sexTYpe[] = [
     { label: "男", value: '1' },

+ 4 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/component/attachment.vue

@@ -61,6 +61,7 @@ const attachmenttable = ref([])
 const information = ref<any>({})
 const renameDialogVisible = ref(false)
 const renameVal = ref('')
+const uploadRef = ref<any>()
 
 // 下载文件
 function fileDownload(item: any) {
@@ -106,7 +107,9 @@ async function httpUploadFile(param: UploadRequestOptions) {
     const formData = new FormData();
     formData.append('file', param.file)
     formData.append('id', bussinessId)
-    const res = await uploadFile(UPLOADFILEFILE, formData)
+    const res = await uploadFile(UPLOADFILEFILE, formData).finally(() => {
+        uploadRef.value.clearFiles()
+    })
     if (res.code == 'ok') {
         globalPopup?.showSuccess(res.msg || '')
         emits('refreshData');

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/index.vue

@@ -270,7 +270,7 @@ function editNewBusiness(item: any) {
   }
   if (!item) {
     businessTemplateValue.value = {}
-    allText.newBusinessisibleText = '新建产品'
+    allText.newBusinessisibleText = '新建商机'
   }
   setTimeout(() => {
     businessTemplateRef.value && businessTemplateRef.value.reset()

+ 1 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/api.ts

@@ -17,6 +17,7 @@ export const URL_DETELEITEM = `${URL}/confirmDeleteContacts`
 export const URL_RESTORE = `${URL}/returnContacts`
 export const URL_GETALL = `${URL}/getAllContacts`
 export const URL_GETDETAIL = `${URL}/getContactsDetail`
+export const URL_TRANSFERCONTACTS = `${URL}/transferContacts`
 
 export const actionButtons: any[] = [
     { text: '新建联系人' },

+ 120 - 44
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/attachment.vue

@@ -3,64 +3,140 @@
         <div class="flex justify-between">
             <div class="title">附件</div>
             <div>
-                <el-button type="primary">上传</el-button>
+                <el-upload ref="uploadRef" :http-request="httpUploadFile" :limit="1" :show-file-list="false"
+                    element-loading-text="正在上传" :loading="allLoading.uploadFileLoading">
+                    <template #trigger>
+                        <el-button type="primary">上传</el-button>
+                    </template>
+                </el-upload>
             </div>
         </div>
         <div class="flex-1 overflow-auto pt-3">
             <el-table :data="attachmenttable" border style="width: 100%;height: 200px;">
-                <el-table-column prop="fileName" label="附件名称" width="180" />
-                <el-table-column prop="fileSize" label="附件大小" width="120" />
-                <el-table-column prop="uploader" label="上传人" width="120" />
-                <el-table-column prop="uploadTime" label="上传时间" width="180" />
+                <el-table-column prop="documentName" label="附件名称" width="180" />
+                <el-table-column prop="size" label="附件大小" width="120" />
+                <el-table-column prop="creatorName" label="上传人" width="120" />
+                <el-table-column prop="indate" label="上传时间" width="180" />
                 <el-table-column label="操作" width="180" fixed="right">
                     <template #default="scope">
-                        <el-button link type="primary" size="large">下载</el-button>
-                        <el-button link type="primary" size="large">重命名</el-button>
-                        <el-button link type="danger" size="large">删除</el-button>
+                        <el-button link type="primary" size="large" @click="fileDownload(scope.row)">下载</el-button>
+                        <el-button link type="primary" size="large" @click="operation(scope.row)">重命名</el-button>
+                        <el-button link type="danger" size="large" @click="fileDetele(scope.row)">删除</el-button>
                     </template>
                 </el-table-column>
             </el-table>
         </div>
+
+        <!-- 弹窗 -->
+        <el-dialog v-model="allVisible.renameDialogVisible" width="800" :show-close="false" top="10vh">
+            <template #header="{ close, titleId, titleClass }">
+                <div class="flex justify-between items-center border-b pb-3 dialog-header">
+                    <h4 :id="titleId">{{ '文件重命名' }}</h4>
+                    <div>
+                        <el-button type="primary" @click="saveEditClue()" :loading="allLoading.saveLoading">保存</el-button>
+                        <el-button @click="allVisible.renameDialogVisible = false">取消</el-button>
+                    </div>
+                </div>
+            </template>
+            <div class="pt-3">
+                <el-input v-model.trim="fileFormVal.name" style="width: 100%" class="pb-3" clearable />
+            </div>
+        </el-dialog>
     </div>
 </template>
 <script lang="ts" setup>
+import { post, uploadFile } from '@/utils/request';
+import { UploadRequestOptions } from 'element-plus';
 import { ref, reactive, onMounted, onUnmounted, defineExpose, inject, watchEffect } from 'vue'
+import { URLFILEDETELE, URL_REFNAME, URL_UPLOADFILE } from '@/pages/api';
+import { downloadFile } from '@/utils/tools';
+
+const globalPopup = inject<GlobalPopup>('globalPopup')
+const emits = defineEmits(['refreshData']);
+const props = defineProps<{
+    data: any
+}>()
+
+type fileFormVal = {
+    id?: string,
+    name?: string
+}
+
+const uploadRef = ref<any>()
+const information = ref<any>({})
+const attachmenttable = ref([])
+const fileTypeStr = ref('') // 文件重命名的类型
+const fileFormVal = ref<fileFormVal>({})
+const allLoading = reactive({
+    uploadFileLoading: false,
+    saveLoading: false
+})
+const allVisible = reactive({
+    renameDialogVisible: false
+})
+
+function saveEditClue() {
+    if(!fileFormVal.value.name) {
+        globalPopup?.showWarning('请输入文件名称')
+        return
+    }
+    allLoading.saveLoading = true
+    post(URL_REFNAME, {
+        fileId: fileFormVal.value.id,
+        newName: fileFormVal.value.name + '.' + fileTypeStr.value
+    }).then(() => {
+        allVisible.renameDialogVisible = false
+        globalPopup?.showSuccess('重命名成功')
+        emits('refreshData');
+    }).finally(() => {
+        allLoading.saveLoading = false
+    })
+}
+
+function operation(item: any) {
+    fileTypeStr.value = item.documentName.split('.').pop()
+    fileFormVal.value = {
+        id: item.id,
+        name: item.documentName.replace(/\.[^/.]+$/, '')
+    }
+    allVisible.renameDialogVisible = true
+}
+
+function fileDownload(item: any) {
+    downloadFile(`${item.url}`, item.documentName)
+}
+
+function fileDetele(item: any) {
+    post(URLFILEDETELE, { fileIds: item.id }).then(() => {
+        globalPopup?.showSuccess('删除成功')
+        emits('refreshData');
+    })
+}
+
+// 上传附件
+async function httpUploadFile(param: UploadRequestOptions) {
+    const id = information.value.id
+    const formData = new FormData();
+    formData.append('file', param.file)
+    formData.append('contactsId', id)
+    allLoading.uploadFileLoading = true
+    const res = await uploadFile(URL_UPLOADFILE, formData).finally(() => {
+        allLoading.uploadFileLoading = false
+        uploadRef.value.clearFiles()
+    })
+    if (res.code == 'ok') {
+        globalPopup?.showSuccess(res.msg || '')
+        emits('refreshData');
+        return
+    }
+    globalPopup?.showError(res.msg || '')
+    return res
+}
 
-const attachmenttable = ref([{
-    fileName: '文件附件',
-    fileSize: '3.1MB',
-    uploader: '张三',
-    uploadTime: '2024-04-01',
-}, {
-    fileName: '文件附件',
-    fileSize: '3.1MB',
-    uploader: '张三',
-    uploadTime: '2024-04-01',
-}, {
-    fileName: '文件附件',
-    fileSize: '3.1MB',
-    uploader: '张三',
-    uploadTime: '2024-04-01',
-}, {
-    fileName: '文件附件',
-    fileSize: '3.1MB',
-    uploader: '张三',
-    uploadTime: '2024-04-01',
-}, {
-    fileName: '文件附件',
-    fileSize: '3.1MB',
-    uploader: '张三',
-    uploadTime: '2024-04-01',
-}, {
-    fileName: '文件附件',
-    fileSize: '3.1MB',
-    uploader: '张三',
-    uploadTime: '2024-04-01',
-}, {
-    fileName: '文件附件',
-    fileSize: '3.1MB',
-    uploader: '张三',
-    uploadTime: '2024-04-01',
-}])
+watchEffect(() => {
+    const { data } = props
+    information.value = data
+    attachmenttable.value = data.contactsDocumentList || []
+});
 </script>
 <style scoped lang="scss"></style>

+ 3 - 3
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/deteleTables.vue

@@ -3,7 +3,7 @@
         top="10vh">
         <template #header="{ close, titleId, titleClass }">
             <div class="flex justify-between items-center border-b pb-3 dialog-header">
-                <h4 :id="titleId">商机回收站</h4>
+                <h4 :id="titleId">联系人回收站</h4>
                 <div>
                     <el-button type="primary" v-loading="allLoading.batchRecoveryLoading" :disabled="batchTableData.length == 0"
                         @click="batchOperation('恢复')">批量恢复</el-button>
@@ -118,8 +118,8 @@ function getTableList() {
     allLoading.tableLoading = true
     post(URL_RECYCLELIST, { ...tableForm }).then((res) => {
         if (res.code == 'ok') {
-            const { data, total } = res.data
-            deteleBusinessTable.value = data.map((item: any) => {
+            const { records, total } = res.data
+            deteleBusinessTable.value = records.map((item: any) => {
                 return {
                     ...item,
                     expectedTransactionDate: formatDate(new Date(item.expectedTransactionDate))

+ 164 - 28
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/information.vue

@@ -3,8 +3,9 @@
         <div class="flex justify-between">
             <div class="title">基本信息</div>
             <div>
-                <el-button type="primary">转移</el-button>
-                <el-button type="primary">编辑</el-button>
+                <el-button type="primary" v-if="!info.ownerId">认领</el-button>
+                <el-button type="primary" v-else @click="operationCli(false)">转移</el-button>
+                <el-button type="primary" @click="editInfo(info)">编辑</el-button>
             </div>
         </div>
         <div class="form flex flex-wrap justify-between">
@@ -13,54 +14,189 @@
                 <div class="flex-1 overflow-hidden text-ellipsis whitespace-nowrap ml-1">{{ item.value }}</div>
             </div>
         </div>
+
+        <el-dialog v-model="allVisible.editContactsVisible" width="1000" :show-close="false" top="10vh">
+            <template #header="{ close, titleId, titleClass }">
+                <div class="flex justify-between items-center border-b pb-3 dialog-header">
+                    <h4 :id="titleId">编辑联系人</h4>
+                    <div>
+                        <el-button type="primary" @click="editContactsSave()"
+                            :loading="allLoading.editContactsSaveLoading">保存</el-button>
+                        <el-button @click="closeVisible('editContactsVisible')">取消</el-button>
+                    </div>
+                </div>
+            </template>
+            <div class="h-[60vh] overflow-y-auto scroll-bar pt-3">
+                <div class="ml-4 mr-4">
+                    <GenerateForm ref="contactsTemplateRef" :data="contactsTemplate" :value="contactsTemplateValue"
+                        :key="contactsTemplateRefKey" v-loading="allLoading.contactsTemplateRefLoading" />
+                </div>
+            </div>
+        </el-dialog>
+
+        <el-dialog v-model="allVisible.transferVisible" width="600" :show-close="false" top="10vh">
+            <template #header="{ close, titleId, titleClass }">
+                <div class="flex justify-between items-center border-b pb-3 dialog-header">
+                    <h4 :id="titleId">{{ allText.operationText }}</h4>
+                    <div>
+                        <el-button type="primary" :loading="allLoading.transferLoading"
+                            @click="transferBusiness(true)">转移</el-button>
+                        <el-button @click="allVisible.transferVisible = false">取消</el-button>
+                    </div>
+                </div>
+            </template>
+            <div class="scroll-bar m-6">
+                <div class="flex mb-4">
+                    <div class="w-20 flex items-center justify-end pr-4">转移至:</div>
+                    <el-select v-model="transferValue" placeholder="请选择" class="flex1">
+                        <el-option v-for="item in transferOptions" :key="item.value" :label="item.label"
+                            :value="item.value" />
+                    </el-select>
+                </div>
+                <div class="pl-3 text-[#e94a4a]">转移后,将看不到此联系人</div>
+            </div>
+        </el-dialog>
     </div>
 </template>
 <script lang="ts" setup>
 import { ref, reactive, onMounted, onUnmounted, defineExpose, inject, watchEffect } from 'vue'
+import { GenerateForm } from '@zmjs/form-design';
+import { getFromValue, getTemplateKey } from '@/utils/tools';
+import { GETGENERATEFOEM, GETPERSONNEL, URL_TRANSFERCONTACTS, URL_UPLOAD } from '../api';
+import { get, post } from '@/utils/request';
 
+const globalPopup = inject<GlobalPopup>('globalPopup')
+const emits = defineEmits(['refreshData']);
 const props = defineProps<{
     data: any
 }>()
-
+const allLoading = reactive({
+    contactsTemplateRefLoading: false,
+    editContactsSaveLoading: false,
+    transferLoading: false
+})
+const allVisible = reactive({
+    editContactsVisible: false,
+    transferVisible: false
+})
+const allText = reactive({
+    operationText: '认领联系人'
+})
+const contactsTemplate = ref({
+    list: [],
+    config: {}
+})
+const contactsTemplateValue = ref({})
+const contactsTemplateRef = ref<typeof GenerateForm>()
+const contactsTemplateRefKey = ref(1)
 const info: any = ref({})
+const transferValue = ref('')
+const transferOptions = ref<optionType[]>([])
+
+function operationCli(flag: boolean) {
+    transferValue.value = flag ? '' : info.value.ownerId
+    allText.operationText = flag ? '认领联系人' : '转移联系人'
+    showVisible('transferVisible')
+}
+
+function transferBusiness(flag: boolean) {
+    const url = flag ? URL_TRANSFERCONTACTS : ''
+    const formVal = flag ? { id: info.value.id, ownerId: transferValue.value } : {}
+    allLoading.transferLoading = true
+    post(url, { ...formVal }).then((_res) => {
+        closeVisible('transferVisible')
+        globalPopup?.showSuccess('转移成功')
+        emits('refreshData')
+    }).finally(() => {
+        allLoading.transferLoading = false
+    })
+}
+
+function editInfo(row: any) {
+    showVisible('editContactsVisible')
+    const templateKey = getTemplateKey(contactsTemplate.value.list)
+    const formVal: templateKey = { id: row.id }
+    for (let i in templateKey) {
+        if (row[templateKey[i]] || row[templateKey[i]] == 0) {
+            formVal[templateKey[i]] = templateKey[i] == 'sex' ? row[templateKey[i]] + '' : row[templateKey[i]]
+        }
+    }
+    setTemplateVal(formVal)
+}
+
+function editContactsSave(flag: boolean = false) {
+    contactsTemplateRef.value?.getData().then((res: any) => {
+        let formVal = getFromValue({ ...contactsTemplateValue.value, ...res })
+        allLoading.editContactsSaveLoading = true
+        post(URL_UPLOAD, { ...formVal }).then((_res) => {
+            allVisible.editContactsVisible = flag
+            globalPopup?.showSuccess('保存成功')
+            emits('refreshData')
+        }).finally(() => {
+            allLoading.editContactsSaveLoading = false
+        })
+    }).catch((_err: any) => {
+        console.log(_err)
+        globalPopup?.showError('请填写完整')
+    })
+}
+
+function setTemplateVal(val: any = {}) {
+    contactsTemplateValue.value = val
+    allLoading.contactsTemplateRefLoading = true
+    setTimeout(() => {
+        contactsTemplateRefKey.value++
+        allLoading.contactsTemplateRefLoading = false
+    }, 1000);
+}
+
+function showVisible(type: keyof typeof allVisible) {
+    allVisible[type] = true
+}
+
+function closeVisible(type: keyof typeof allVisible) {
+    allVisible[type] = false
+}
 
 const formItems = reactive([
-    { label: '联系人', key: 'productCode', value: '', labelClass: 'w-20 text-right text-gray-500', width: '48%' },
+    { label: '联系人', key: 'name', value: '', labelClass: 'w-20 text-right text-gray-500', width: '48%' },
     { label: '客户', key: 'productName', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '电话号码', key: 'typeName', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '邮箱', key: 'unitName', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '职务', key: 'price', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '性别', key: 'unit', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '地址', key: 'status', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
+    { label: '电话', key: 'phone', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
+    { label: '邮箱', key: 'email', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
+    { label: '职务', key: 'position', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
+    { label: '性别', key: 'sexValue', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
+    { label: '地址', key: 'address', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
     { label: '负责人', key: 'inchargerName', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
     { label: '创建人', key: 'creatorName', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
     { label: '创建时间', key: 'createTime', value: '', labelClass: 'w-22 text-right text-gray-500', width: '48%' },
-    { label: '备注', key: 'descs', value: '', labelClass: 'w-22 text-right text-gray-500', width: '100%' },
+    { label: '备注', key: 'remark', value: '', labelClass: 'w-22 text-right text-gray-500', width: '100%' },
 ])
 
 watchEffect(() => {
-
+    const { data } = props
+    info.value = data
+    formItems.forEach(item => {
+        item.value = info.value[item.key];
+    });
 });
 
+async function getSystemField() {
+    const { data } = await post(GETPERSONNEL, {})
+    transferOptions.value = data.map((item: any) => {
+        const { id, name, phone, jobNumber } = item
+        return {
+            value: id,
+            label: name
+        }
+    })
+
+    const datas = await get(GETGENERATEFOEM)
+    contactsTemplate.value = JSON.parse(datas.data[0].config)
+}
+
 // 生命周期钩子
 onMounted(async () => {
-    info.value = {
-        productCode: '联系的人',
-        productName: '客户名称',
-        typeName: '电话号码',
-        unitName: '邮箱地址',
-        price: '职务',
-        unit: '性别',
-        status: 1,
-        inchargerName: '负责人姓名',
-        creatorName: '创建人姓名',
-        createTime: '创建时间',
-        descs: '备注信息'
-    };
-
-    formItems.forEach(item => {
-        item.value = info.value[item.key];
-    });
+    getSystemField()
 });
 </script>
 <style scoped lang="scss">

+ 13 - 33
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/operationRecord.vue

@@ -5,45 +5,25 @@
         </div>
         <div class="flex-1 overflow-auto pt-5">
             <el-table :data="operationRecordtable" border style="width: 100%;height: 278px;">
-                <el-table-column prop="operatingTime" label="操作时间" width="140" />
-                <el-table-column prop="operator" label="操作人" width="120" />
-                <el-table-column prop="operationContent" label="操作内容" />
+                <el-table-column prop="operateDate" label="操作时间" width="150" />
+                <el-table-column prop="operateName" label="操作人" width="120" />
+                <el-table-column prop="msg" label="操作内容" />
             </el-table>
         </div>
     </div>
 </template>
 <script lang="ts" setup>
-import { ref, reactive, onMounted, onUnmounted, defineExpose, inject } from 'vue'
+import { ref, reactive, onMounted, onUnmounted, defineExpose, inject, watchEffect } from 'vue'
+const props = defineProps<{
+    data: any
+}>()
 
-const operationRecordtable = ref([{
-    operationContent: '转移线索',
-    operator: '张三',
-    operatingTime: '2024-04-01',
-}, {
-    operationContent: '转移线索',
-    operator: '张三',
-    operatingTime: '2024-04-01',
-}, {
-    operationContent: '转移线索',
-    operator: '张三',
-    operatingTime: '2024-04-01',
-}, {
-    operationContent: '转移线索',
-    operator: '张三',
-    operatingTime: '2024-04-01',
-}, {
-    operationContent: '转移线索',
-    operator: '张三',
-    operatingTime: '2024-04-01',
-}, {
-    operationContent: '转移线索',
-    operator: '张三',
-    operatingTime: '2024-04-01',
-}, {
-    operationContent: '转移线索',
-    operator: '张三',
-    operatingTime: '2024-04-01',
-},])
+const operationRecordtable = ref([])
+
+watchEffect(() => {
+    const { data } = props
+    operationRecordtable.value = data.contactsLogList || []
+});
 // 生命周期钩子
 onMounted(() => {
 });

+ 170 - 57
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/relatedBusiness.vue

@@ -3,78 +3,191 @@
         <div class="flex justify-between">
             <div class="title">相关商机</div>
             <div>
-                <el-button type="primary">新建商机</el-button>
+                <el-button type="primary" @click="addBusiness()">新建商机</el-button>
             </div>
         </div>
         <div class="flex-1 overflow-auto pt-3">
-            <el-table :data="relatedTaskstable" border style="width: 100%;height: 100%;">
-                <el-table-column prop="taskName" label="商机名称">
+            <el-table :data="relatedTaskstable" border height="300" style="width: 100%;">
+                <el-table-column prop="name" label="商机名称">
                     <template #default="scope">
-                        <el-button link type="primary" size="large">{{
-                            scope.row.taskName
+                        <el-button link type="primary" size="large" @click="toBusDetal(scope.row)">{{
+                            scope.row.name
                         }}</el-button>
                     </template>
                 </el-table-column>
-                <el-table-column prop="priority" label="客户名称" width="130" />
-                <el-table-column prop="status" label="负责人" width="130" />
-                <el-table-column prop="executor" label="商机金额" width="130" />
-                <el-table-column prop="startTime" label="预计成交时间" width="130" />
-                <el-table-column prop="endTime" label="商机阶段" width="130" />
-                <el-table-column prop="endTime" label="创建人" width="130" />
-                <el-table-column prop="endTime" label="创建时间" width="130" />
-                <el-table-column prop="endTime" label="修改时间" width="130" />
+                <el-table-column prop="customerName" label="客户名称" width="130" />
+                <el-table-column prop="inchargerName" label="负责人" width="130" />
+                <el-table-column prop="amountOfMoney" label="商机金额" width="130" />
+                <el-table-column prop="expectedTransactionDate" label="预计成交时间" width="170" />
+                <el-table-column prop="stageValue" label="商机阶段" width="130" />
+                <el-table-column prop="creatorName" label="创建人" width="130" />
+                <el-table-column prop="createTime" label="创建时间" width="130" />
+                <el-table-column prop="modifyTime" label="修改时间" width="130" />
             </el-table>
         </div>
+
+        <!-- 弹窗 -->
+        <el-dialog v-model="allVisible.newBusinessisible" width="1000" :show-close="false" top="10vh">
+            <template #header="{ close, titleId, titleClass }">
+                <div class="flex justify-between items-center border-b pb-3 dialog-header">
+                    <h4 :id="titleId">新建商机</h4>
+                    <div>
+                        <el-button type="primary" @click="editBusiness()"
+                            :loading="allLoading.businessSaveLading">保存</el-button>
+                        <el-button @click="closeVisible('newBusinessisible')">取消</el-button>
+                    </div>
+                </div>
+            </template>
+            <div class="h-[60vh] overflow-y-auto scroll-bar pt-3" v-loading="allLoading.generateFormLading">
+                <GenerateForm ref="businessTemplateRef" :data="businessTemplate" :value="businessTemplateValue"
+                    :key="businessTemplateKey" />
+                <div>相关产品</div>
+                <RelatedProducts ref="relatedProductsRef" :productTableList="productTableList" />
+            </div>
+        </el-dialog>
     </div>
 </template>
 <script lang="ts" setup>
-import { ref, reactive, onMounted, onUnmounted, defineExpose, inject } from 'vue'
+import { ref, reactive, onMounted, onUnmounted, defineExpose, inject, watchEffect } from 'vue'
+import { GenerateForm } from '@zmjs/form-design';
+import { get, post } from '@/utils/request';
+import { useRouter, useRoute } from "vue-router";
+
+import RelatedProducts from '@/components/relatedProducts/relatedProducts.vue'
+import { formatDateTime } from '@/utils/times';
+import { GETGENERATEFOEM, UPDATEINSET } from '@/pages/business/api';
+import { GETTABLELIST } from '@/pages/product/api';
+
+const router = useRouter()
+const globalPopup = inject<GlobalPopup>('globalPopup')
+const emits = defineEmits(['refreshData']);
+const props = defineProps<{
+    data: any
+}>()
+
+const information = ref<any>({})
+const relatedTaskstable = ref([])
+const businessTemplateRef = ref<typeof GenerateForm>() // 自定义表单dom
+const relatedProductsRef = ref<typeof RelatedProducts>()
+const productTableList = ref([])
+const businessTemplateValue = ref({})
+const businessTemplateKey = ref(1)
+const businessTemplate = ref({
+    config: {},
+    list: []
+}) // 自定义表单数据
+const allLoading = reactive({
+    newBusinessSaveLading: false,
+    businessSaveLading: false,
+    generateFormLading: false
+})
+const allVisible = reactive({
+    newBusinessisible: false
+})
+
+function toBusDetal(row: any) {
+    router.push({
+        path: `/business/detail`,
+        query: { id: row.id }
+    })
+}
+
+function editBusiness() {
+    businessTemplateRef.value?.getData().then((res: any) => {
+        let productTableListData = relatedProductsRef?.value?.returnData()
+        let newForm = {
+            ...res,
+            expectedTransactionDate: res.expectedTransactionDate ? formatDateTime(new Date(res.expectedTransactionDate)) : '',
+            businessItemProductList: productTableListData ? JSON.stringify(productTableListData) : []
+        }
+        allLoading.businessSaveLading = true
+        post(UPDATEINSET, { ...businessTemplateValue.value, ...newForm }).then((_res) => {
+            allVisible.newBusinessisible = false
+            globalPopup?.showSuccess('保存成功')
+            emits('refreshData')
+        }).finally(() => {
+            allLoading.businessSaveLading = false
+        })
+    }).catch((_err: any) => {
+        console.log(_err)
+        globalPopup?.showError('请填写完整')
+    })
+}
+
+function addBusiness() {
+    showVisible('newBusinessisible')
+    allLoading.generateFormLading = true
+    businessTemplateValue.value = {
+        customerId: information.value.customId,
+        contactsId: information.value.id
+    }
+    setTimeout(() => {
+        businessTemplateRef.value && businessTemplateRef.value.reset()
+        businessTemplateKey.value++
+        allLoading.generateFormLading = false
+    }, 500)
+}
+
+function showVisible(type: keyof typeof allVisible) { // 显示弹窗
+    allVisible[type] = true
+}
+
+function closeVisible(type: keyof typeof allVisible) {
+    allVisible[type] = false
+}
+
+watchEffect(() => {
+    const { data } = props
+    information.value = data
+    relatedTaskstable.value = data.businessOpportunityList
+});
+
+async function getSystemField() {
+    const res = await get(GETGENERATEFOEM)
+    let config = JSON.parse(res.data[0].config)
+    config.list.forEach((item: any) => {
+        if (item.type == "grid") {
+            item.columns.forEach((column: any) => {
+                column.list.forEach((newColumn: any) => {
+                    if (newColumn.model == 'customerId' || newColumn.model == "contactsId") {
+                        newColumn.options.disabled = true
+                    }
+                })
+            })
+        }
+    })
+    businessTemplate.value = config
+}
 
-const relatedTaskstable = ref([{
-    taskName: '相关商机',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '相关商机',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '相关商机',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '相关商机',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '相关商机',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '相关商机',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}])
+function getProductTableList() {
+    post(GETTABLELIST, { pageIndex: -1, pageSize: -1 }).then((res) => {
+        if (res.code == 'ok') {
+            const { record, total } = res.data
+            productTableList.value = record.map((item: any) => {
+                const { id, productName, productCode, unit, unitName, typeName, type, price, inventory } = item
+                return {
+                    id,
+                    productId: id,
+                    productName,
+                    productCode,
+                    unit,
+                    unitName,
+                    price,
+                    type,
+                    typeName,
+                    inventory,
+                    quantity: '',
+                    discount: '',
+                    totalPrice: ''
+                }
+            })
+        }
+    })
+}
 // 生命周期钩子
 onMounted(() => {
+    getSystemField()
+    getProductTableList()
 });
 </script>
 <style scoped lang="scss"></style>

+ 1 - 43
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/component/relatedTasks.vue

@@ -27,49 +27,7 @@
 <script lang="ts" setup>
 import { ref, reactive, onMounted, onUnmounted, defineExpose, inject } from 'vue'
 
-const relatedTaskstable = ref([{
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}, {
-    taskName: '任务名称20240316-tempalsbls',
-    priority: '中',
-    status: '进行中',
-    executor: '张三',
-    startTime: '2024-04-01',
-    endTime: '2024-04-01',
-}])
+const relatedTaskstable = ref([])
 // 生命周期钩子
 onMounted(() => {
 });

+ 8 - 9
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/detail/index.vue

@@ -7,7 +7,7 @@
                 </el-link>
             </div>
             <div class="mr-8">
-                <el-select v-model="values" placeholder="请选择" style="width: 150px">
+                <el-select v-model="values" placeholder="请选择" style="width: 300px" @change="getDetail">
                     <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
                 </el-select>
             </div>
@@ -16,10 +16,10 @@
         <div class="flex-1 flex flex-col overflow-y-auto overflow-x-hidden scroll-bar" v-loading="pageLoading">
             <div class="w-full h-auto flex justify-between">
                 <div class="bg-white shadow-md rounded-md" style="width: 46%;">
-                    <Information :data="information" />
+                    <Information :data="information" @refreshData="getDetail" />
                 </div>
                 <div class="bg-white ml-2 shadow-md rounded-md flex-1">
-                    <Attachment :data="attachment" :information="information" />
+                    <Attachment :data="information" @refreshData="getDetail" />
                 </div>
             </div>
 
@@ -29,13 +29,13 @@
                     <Detailcompinents :data="relatedTasks" :information="information" :formTaskType="0" :filed="'contactsId'" :disabledList="['contactsId']" @refreshData="getDetail" />
                 </div>
                 <div class="bg-white ml-2 shadow-md rounded-md flex-1">
-                    <OperationRecord :data="operationRecord" />
+                    <OperationRecord :data="information" />
                 </div>
             </div>
 
             <div class="w-full h-auto flex justify-between mt-2">
                 <div class="bg-white shadow-md rounded-md w-full">
-                    <RelatedBusiness :data="relatedBusiness" />
+                    <RelatedBusiness :data="information" @refreshData="getDetail" />
                 </div>
             </div>
         </div>
@@ -60,10 +60,7 @@ import RelatedBusiness from '../component/relatedBusiness.vue'
 const route = useRoute()
 const globalPopup = inject<GlobalPopup>('globalPopup')
 const information = ref({}) // 基本信息
-const attachment = ref([]) // 附件
 const relatedTasks = ref([]) // 相关任务
-const operationRecord = ref([]) // 操作记录
-const relatedBusiness = ref([]) // 相关商机
 const rowId = ref(+(route.query.id || ''))
 const values = ref<number | string>('')
 const options = ref<optionType[]>([])
@@ -72,7 +69,9 @@ const pageLoading = ref(false)
 function getDetail() {
     pageLoading.value = true
     post(URL_GETDETAIL, { id: rowId.value }).then((res) => {
-        console.log(res)
+        res.data.sexValue = res.data.sex === 1 ? '男' : '女'
+        information.value = res.data
+        relatedTasks.value = res.data.taskList
     }).finally(() => {
         pageLoading.value = false
     })

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contacts/index.vue

@@ -261,7 +261,7 @@ function contactsDeteleItem(value: string | number, label: string, batch: boolea
       changeBatch(false)
       getContactPerson()
     }).catch((err) => {
-      globalPopup?.showError(err.message)
+      globalPopup?.showError(err.msg)
     })
   })
 }

+ 59 - 21
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserWithBeisenController.java

@@ -229,7 +229,12 @@ public class UserWithBeisenController {
                         List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
                                 && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)).collect(Collectors.toList());
                         //加班数据可能存在结束日期是当前日期的情况的情况
-                        BigDecimal overTimeBigDecimal = new BigDecimal(0);
+                        BigDecimal overTimeBigDecimal;
+                        if(workDay){
+                            overTimeBigDecimal = new BigDecimal(0);
+                        }else {
+                            overTimeBigDecimal = new BigDecimal(8);
+                        }
                         for (JSONObject o : overTimeList) {
                             //存在开始日期为当前日期的数据以及结束日期为当天日期的数据 分开计算
                             if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(localDate)){
@@ -247,7 +252,9 @@ public class UserWithBeisenController {
 //                                        if(max.get().isAfter(LocalTime.parse("18:00:00",df4))){
 //                                            timeDurantion=timeDurantion.minusMinutes(30);
 //                                        }
-                                        long l = timeDurantion.toMinutes() / 60;
+                                        BigDecimal decimal = new BigDecimal(timeDurantion.toMinutes());
+                                        decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                        double l = decimal.doubleValue();
                                         if(l<o.getDouble("OverTimeDuration")){
                                             overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l));
                                         }else {
@@ -266,11 +273,15 @@ public class UserWithBeisenController {
 //                                    if(stop.toLocalTime().isAfter(LocalTime.parse("18:00:00",df4))){
 //                                        duration=duration.minusMinutes(30);
 //                                    }
-                                    long l = duration.toMinutes() / 60;
+                                    BigDecimal decimal = new BigDecimal(duration.toMinutes());
+                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                    double l = decimal.doubleValue();
                                     if(max.get().isAfter(LocalTime.parse("19:00:00",df4))){
                                         //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
                                         Duration timeDurantion = Duration.between(LocalTime.parse("18:00:00", df4), max.get());
-                                        long l1 = timeDurantion.toMinutes() / 60;
+                                        BigDecimal decimal1 = new BigDecimal(timeDurantion.toMinutes());
+                                        decimal1=decimal1.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                        double l1 = decimal1.doubleValue();
                                         if(l1<l){
                                             overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l1));
                                         }else {
@@ -293,7 +304,9 @@ public class UserWithBeisenController {
 //                                        if(max.get().isAfter(LocalTime.parse("18:00:00",df4))){
 //                                            timeDurantion=timeDurantion.minusMinutes(30);
 //                                        }
-                                        long l = timeDurantion.toMinutes() / 60;
+                                        BigDecimal decimal = new BigDecimal(timeDurantion.toMinutes());
+                                        decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                        double l = decimal.doubleValue();
                                         if(l<o.getDouble("OverTimeDuration")){
                                             overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l));
                                         }else {
@@ -313,11 +326,15 @@ public class UserWithBeisenController {
 //                                    if(stop.toLocalTime().isAfter(LocalTime.parse("18:00:00",df4))){
 //                                        duration=duration.minusMinutes(30);
 //                                    }
-                                    long l = duration.toMinutes() / 60;
+                                    BigDecimal decimal = new BigDecimal(duration.toMinutes());
+                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                    double l = decimal.doubleValue();
                                     if(max.get().isAfter(LocalTime.parse("19:00:00",df4))){
                                         //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
                                         Duration timeDurantion = Duration.between(LocalTime.parse("18:00:00", df4), max.get());
-                                        long l1 = timeDurantion.toMinutes() / 60;
+                                        BigDecimal decimal1 = new BigDecimal(timeDurantion.toMinutes());
+                                        decimal1=decimal1.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                        double l1 = decimal1.doubleValue();
                                         if(l1<l){
                                             overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l1));
                                         }else {
@@ -332,10 +349,12 @@ public class UserWithBeisenController {
                             workTime= workTime+overTimeBigDecimal.doubleValue();
                         }else {
                             //非工作日加班 根据实际打卡时长 比较 加班单时长
-                            if((between.toMinutes()/60)>overTimeBigDecimal.doubleValue()){
+                            BigDecimal decimal = new BigDecimal(between.toMinutes());
+                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                            if((decimal.doubleValue())>overTimeBigDecimal.doubleValue()){
                                 workTime= workTime+overTimeBigDecimal.doubleValue();
                             }else {
-                                workTime= workTime+(between.toMinutes()/60);
+                                workTime= workTime+(decimal.doubleValue());
                             }
                         }
                         //处理修改
@@ -428,10 +447,9 @@ public class UserWithBeisenController {
                     leaveSheet.setStatus(jsonObject.getString("ApproveStatus").equals("通过")?0:jsonObject.getString("Reason").equals("审批中")?1:2);
                     leaveSheet.setProcinstId(jsonObject.getString("VacationId"));
                     LeaveSheet one = leaveSheetService.getOne(new LambdaQueryWrapper<LeaveSheet>().eq(LeaveSheet::getProcinstId,leaveSheet.getProcinstId()).eq(LeaveSheet::getOwnerId, first.get().getId()).eq(LeaveSheet::getStartDate, leaveSheet.getStartDate()).eq(LeaveSheet::getEndDate, endDate));
-                    if(one!=null){
-                        leaveSheet.setId(one.getId());
+                    if(one==null){
+                        leaveSheetList.add(leaveSheet);
                     }
-                    leaveSheetList.add(leaveSheet);
                 }
             }
         }
@@ -511,7 +529,12 @@ public class UserWithBeisenController {
                 List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
                         && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)).collect(Collectors.toList());
                 //加班数据可能存在结束日期是当前日期的情况的情况
-                BigDecimal overTimeBigDecimal = new BigDecimal(0);
+                BigDecimal overTimeBigDecimal;
+                if(workDay){
+                    overTimeBigDecimal = new BigDecimal(0);
+                }else {
+                    overTimeBigDecimal = new BigDecimal(8);
+                }
                 LocalDate localDate = LocalDate.parse(createDate, df);
                 for (JSONObject o : overTimeList) {
                     //存在开始日期为当前日期的数据以及结束日期为当天日期的数据 分开计算
@@ -530,7 +553,10 @@ public class UserWithBeisenController {
 //                                if(max.isAfter(LocalTime.parse("18:00:00",df4))){
 //                                    timeDurantion=timeDurantion.minusMinutes(30);
 //                                }
-                                long l = timeDurantion.toMinutes() / 60;
+                                System.out.println(timeDurantion.toMinutes());
+                                BigDecimal decimal = new BigDecimal(timeDurantion.toMinutes());
+                                decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                double l = decimal.doubleValue();
                                 if(l<o.getDouble("OverTimeDuration")){
                                     overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l));
                                 }else {
@@ -549,11 +575,15 @@ public class UserWithBeisenController {
 //                            if(stop.toLocalTime().isAfter(LocalTime.parse("18:00:00",df4))){
 //                                duration=duration.minusMinutes(30);
 //                            }
-                            long l = duration.toMinutes() / 60;
+                            BigDecimal decimal = new BigDecimal(duration.toMinutes());
+                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                            double l = decimal.doubleValue();
                             if(max.isAfter(LocalTime.parse("19:00:00",df4))){
                                 //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
                                 Duration timeDurantion = Duration.between(LocalTime.parse("18:00:00", df4), max);
-                                long l1 = timeDurantion.toMinutes() / 60;
+                                BigDecimal decimal1 = new BigDecimal(timeDurantion.toMinutes());
+                                decimal1=decimal1.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                double l1 = decimal1.doubleValue();
                                 if(l1<l){
                                     overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l1));
                                 }else {
@@ -576,7 +606,9 @@ public class UserWithBeisenController {
 //                                if(max.isAfter(LocalTime.parse("18:00:00",df4))){
 //                                    timeDurantion=timeDurantion.minusMinutes(30);
 //                                }
-                                long l = timeDurantion.toMinutes() / 60;
+                                BigDecimal decimal = new BigDecimal(timeDurantion.toMinutes());
+                                decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                double l = decimal.doubleValue();
                                 if(l<o.getDouble("OverTimeDuration")){
                                     overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l));
                                 }else {
@@ -596,11 +628,15 @@ public class UserWithBeisenController {
 //                            if(stop.toLocalTime().isAfter(LocalTime.parse("18:00:00",df4))){
 //                                duration=duration.minusMinutes(30);
 //                            }
-                            long l = duration.toMinutes() / 60;
+                            BigDecimal decimal = new BigDecimal(duration.toMinutes());
+                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                            double l = decimal.doubleValue();
                             if(max.isAfter(LocalTime.parse("19:00:00",df4))){
                                 //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
                                 Duration timeDurantion = Duration.between(LocalTime.parse("18:00:00", df4), max);
-                                long l1 = timeDurantion.toMinutes() / 60;
+                                BigDecimal decimal1 = new BigDecimal(timeDurantion.toMinutes());
+                                decimal1=decimal1.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                double l1 = decimal1.doubleValue();
                                 if(l1<l){
                                     overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l1));
                                 }else {
@@ -615,10 +651,12 @@ public class UserWithBeisenController {
                     workTime= workTime+overTimeBigDecimal.doubleValue();
                 }else {
                     //非工作日加班 根据实际打卡时长 比较 加班单时长
-                    if((between.toMinutes()/60)>overTimeBigDecimal.doubleValue()){
+                    BigDecimal decimal = new BigDecimal(between.toMinutes());
+                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                    if((decimal.doubleValue())>overTimeBigDecimal.doubleValue()){
                         workTime= workTime+overTimeBigDecimal.doubleValue();
                     }else {
-                        workTime= workTime+(between.toMinutes()/60);
+                        workTime= workTime+(decimal.doubleValue());
                     }
                 }
                 //处理修改

+ 65 - 47
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java

@@ -2180,7 +2180,12 @@ public class TimingTask {
                         List<JSONObject> overTimeList = overTimeStream.filter(a -> a.getString("StaffId").equals(beisen.get().getUserId())
                                 && (a.getIntValue("ApproveStatus") == 2||a.getIntValue("ApproveStatus") == 1)).collect(Collectors.toList());
                         //加班数据可能存在结束日期是当前日期的情况的情况
-                        BigDecimal overTimeBigDecimal = new BigDecimal(0);
+                        BigDecimal overTimeBigDecimal;
+                        if(workDay){
+                            overTimeBigDecimal = new BigDecimal(0);
+                        }else {
+                            overTimeBigDecimal = new BigDecimal(8);
+                        }
                         for (JSONObject o : overTimeList) {
                             //存在开始日期为当前日期的数据以及结束日期为当天日期的数据 分开计算
                             if(LocalDateTime.parse(o.getString("StartDate"),df1).toLocalDate().isEqual(localDate)){
@@ -2189,16 +2194,18 @@ public class TimingTask {
                                     //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
                                     if(max.get().isAfter(LocalTime.parse("19:00:00",df4))){
                                         //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                                        Duration timeDurantion = Duration.between(LocalTime.parse("19:00:00", df4), max.get());
-                                        //如果结束时间大于13:00
-                                        if(max.get().isAfter(LocalTime.parse("13:00:00",df4))){
-                                            timeDurantion.minusHours(1);
-                                        }
-                                        //如果结束时间大于18:00
-                                        if(max.get().isAfter(LocalTime.parse("18:00:00",df4))){
-                                            timeDurantion.minusMinutes(30);
-                                        }
-                                        long l = timeDurantion.toMinutes() / 60;
+                                        Duration timeDurantion = Duration.between(LocalTime.parse("18:00:00", df4), max.get());
+//                                        //如果结束时间大于13:00
+//                                        if(max.get().isAfter(LocalTime.parse("13:00:00",df4))){
+//                                            timeDurantion.minusHours(1);
+//                                        }
+//                                        //如果结束时间大于18:00
+//                                        if(max.get().isAfter(LocalTime.parse("18:00:00",df4))){
+//                                            timeDurantion.minusMinutes(30);
+//                                        }
+                                        BigDecimal decimal = new BigDecimal(timeDurantion.toMinutes());
+                                        decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                        double l = decimal.doubleValue();
                                         if(l<o.getDouble("OverTimeDuration")){
                                             overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l));
                                         }else {
@@ -2210,18 +2217,22 @@ public class TimingTask {
                                     LocalDateTime start = LocalDateTime.parse(o.getString("StartDate"), df1);
                                     LocalDateTime stop = start.toLocalDate().atTime(LocalTime.MAX);
                                     Duration duration = Duration.between(start, stop);
-                                    if(stop.toLocalTime().isAfter(LocalTime.parse("13:00:00",df4))){
-                                        duration.minusHours(1);
-                                    }
-                                    //如果结束时间大于18:00
-                                    if(stop.toLocalTime().isAfter(LocalTime.parse("18:00:00",df4))){
-                                        duration.minusMinutes(30);
-                                    }
-                                    long l = duration.toMinutes() / 60;
+//                                    if(stop.toLocalTime().isAfter(LocalTime.parse("13:00:00",df4))){
+//                                        duration.minusHours(1);
+//                                    }
+//                                    //如果结束时间大于18:00
+//                                    if(stop.toLocalTime().isAfter(LocalTime.parse("18:00:00",df4))){
+//                                        duration.minusMinutes(30);
+//                                    }
+                                    BigDecimal decimal = new BigDecimal(duration.toMinutes());
+                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                    double l = decimal.doubleValue();
                                     if(max.get().isAfter(LocalTime.parse("19:00:00",df4))){
                                         //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                                        Duration timeDurantion = Duration.between(LocalTime.parse("19:00:00", df4), max.get());
-                                        long l1 = timeDurantion.toMinutes() / 60;
+                                        Duration timeDurantion = Duration.between(LocalTime.parse("18:00:00", df4), max.get());
+                                        BigDecimal decimal1 = new BigDecimal(timeDurantion.toMinutes());
+                                        decimal1=decimal1.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                        double l1 = decimal1.doubleValue();
                                         if(l1<l){
                                             overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l1));
                                         }else {
@@ -2235,16 +2246,18 @@ public class TimingTask {
                                     //开始日期和结束日期是相同的情况 说明是加班区间只存在于当天的情况
                                     if(max.get().isAfter(LocalTime.parse("19:00:00",df4))){
                                         //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                                        Duration timeDurantion = Duration.between(LocalTime.parse("19:00:00", df4), max.get());
-                                        //如果结束时间大于13:00
-                                        if(max.get().isAfter(LocalTime.parse("13:00:00",df4))){
-                                            timeDurantion.minusHours(1);
-                                        }
-                                        //如果结束时间大于18:00
-                                        if(max.get().isAfter(LocalTime.parse("18:00:00",df4))){
-                                            timeDurantion.minusMinutes(30);
-                                        }
-                                        long l = timeDurantion.toMinutes() / 60;
+                                        Duration timeDurantion = Duration.between(LocalTime.parse("18:00:00", df4), max.get());
+//                                        //如果结束时间大于13:00
+//                                        if(max.get().isAfter(LocalTime.parse("13:00:00",df4))){
+//                                            timeDurantion.minusHours(1);
+//                                        }
+//                                        //如果结束时间大于18:00
+//                                        if(max.get().isAfter(LocalTime.parse("18:00:00",df4))){
+//                                            timeDurantion.minusMinutes(30);
+//                                        }
+                                        BigDecimal decimal = new BigDecimal(timeDurantion.toMinutes());
+                                        decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                        double l = decimal.doubleValue();
                                         if(l<o.getDouble("OverTimeDuration")){
                                             overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l));
                                         }else {
@@ -2256,19 +2269,23 @@ public class TimingTask {
                                     LocalDateTime stop = LocalDateTime.parse(o.getString("StopDate"), df1);
                                     LocalDateTime start = stop.toLocalDate().atTime(LocalTime.MIN);
                                     Duration duration = Duration.between(start, stop);
-                                    //如果结束时间大于13:00
-                                    if(stop.toLocalTime().isAfter(LocalTime.parse("13:00:00",df4))){
-                                        duration.minusHours(1);
-                                    }
-                                    //如果结束时间大于18:00
-                                    if(stop.toLocalTime().isAfter(LocalTime.parse("18:00:00",df4))){
-                                        duration.minusMinutes(30);
-                                    }
-                                    long l = duration.toMinutes() / 60;
+//                                    //如果结束时间大于13:00
+//                                    if(stop.toLocalTime().isAfter(LocalTime.parse("13:00:00",df4))){
+//                                        duration.minusHours(1);
+//                                    }
+//                                    //如果结束时间大于18:00
+//                                    if(stop.toLocalTime().isAfter(LocalTime.parse("18:00:00",df4))){
+//                                        duration.minusMinutes(30);
+//                                    }
+                                    BigDecimal decimal = new BigDecimal(duration.toMinutes());
+                                    decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                    double l = decimal.doubleValue();
                                     if(max.get().isAfter(LocalTime.parse("19:00:00",df4))){
                                         //判断打卡时间是不是大于19:00 通过打卡计算加班时长 与加班单作比较 取小
-                                        Duration timeDurantion = Duration.between(LocalTime.parse("19:00:00", df4), max.get());
-                                        long l1 = timeDurantion.toMinutes() / 60;
+                                        Duration timeDurantion = Duration.between(LocalTime.parse("18:00:00", df4), max.get());
+                                        BigDecimal decimal1 = new BigDecimal(timeDurantion.toMinutes());
+                                        decimal1=decimal1.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                                        double l1 = decimal1.doubleValue();
                                         if(l1<l){
                                             overTimeBigDecimal=overTimeBigDecimal.add(new BigDecimal(l1));
                                         }else {
@@ -2283,10 +2300,12 @@ public class TimingTask {
                             workTime= workTime+overTimeBigDecimal.doubleValue();
                         }else {
                             //非工作日加班 根据实际打卡时长 比较 加班单时长
-                            if((between.toMinutes()/60)>overTimeBigDecimal.doubleValue()){
+                            BigDecimal decimal = new BigDecimal(between.toMinutes());
+                            decimal=decimal.divide(new BigDecimal(60),1,RoundingMode.HALF_UP);
+                            if((decimal.doubleValue())>overTimeBigDecimal.doubleValue()){
                                 workTime= workTime+overTimeBigDecimal.doubleValue();
                             }else {
-                                workTime= workTime+(between.toMinutes()/60);
+                                workTime= workTime+(decimal.doubleValue());
                             }
                         }
                         List<JSONObject> vacationList = vacationStream.filter(a ->{
@@ -2376,10 +2395,9 @@ public class TimingTask {
                     leaveSheet.setStatus(jsonObject.getString("ApproveStatus").equals("通过")?0:jsonObject.getString("Reason").equals("审批中")?1:2);
                     leaveSheet.setProcinstId(jsonObject.getString("VacationId"));
                     LeaveSheet one = leaveSheetService.getOne(new LambdaQueryWrapper<LeaveSheet>().eq(LeaveSheet::getOwnerId, first.get().getId()).eq(LeaveSheet::getStartDate, leaveSheet.getStartDate()).eq(LeaveSheet::getProcinstId,leaveSheet.getProcinstId()).eq(LeaveSheet::getEndDate, endDate));
-                    if(one!=null){
-                        leaveSheet.setId(one.getId());
+                    if(one==null){
+                        leaveSheetList.add(leaveSheet);
                     }
-                    leaveSheetList.add(leaveSheet);
                 }
             }
         }

+ 26 - 6
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

@@ -1426,12 +1426,12 @@
               <!-- 222 -->
             </div>
             <div>
+                <el-cascader v-if="user.userNameNeedTranslate != 1" :size="'small'" v-model="deptIdForHasReport" placeholder="请选择部门" :options="departmentList" :props="{ checkStrictly: true, value: 'id' }" clearable style="width: 200px;" @change="showMonthWorkTime()"></el-cascader>
+                <vueCascader :subjectId="deptIdForHasReport" :size="'small'" :widthStr="'200'" :clearable="true" :subject="trandepartmentList" :radios="true" :distinction="'14'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1" :selectNameChuan="$t('other.allDepartments')"></vueCascader>
                 <el-input style="float:left;width:22%" v-if="user.userNameNeedTranslate != '1'" v-model="searchKeyword" @keyup.enter.native="searchScreen(0)" class="input-with-select" :placeholder="$t('defaultText.pleaseEnterNametoSearch')" clearable="true" size="small">
                     <el-button slot="append" @click="searchScreen(0)" icon="el-icon-search"></el-button>
                 </el-input>
                 <selectCat v-if="user.userNameNeedTranslate == '1'" :filterable="true"  :searchBoxTop="'1'" :size="'small'" :subject="usersList" :subjectId="usersListId" :distinction="'12'" :clearable="true" @selectCal="selectCal"></selectCat>
-                <el-cascader v-if="user.userNameNeedTranslate != 1" :size="'small'" v-model="deptIdForHasReport" placeholder="请选择部门" :options="departmentList" :props="{ checkStrictly: true, value: 'id' }" clearable style="width: 200px;" @change="showMonthWorkTime()"></el-cascader>
-                <vueCascader :size="'small'" :widthStr="'200'" :clearable="true" :subject="departmentList" :radios="true" :distinction="'1'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1" :selectNameChuan="$t('other.allDepartments')" @change="showMonthWorkTime()"></vueCascader>
             </div>
             <div style="float: left; height:32px; padding-top:10px;">
               <span style="width:20px;height:20px;background-color: orange;padding:5px 8px;">待审核</span>
@@ -1613,7 +1613,7 @@
             <div>
                 <div style="margin-top:10px;">
                     <el-cascader v-if="user.userNameNeedTranslate != 1" :size="'small'" v-model="deptIdForNoReport" placeholder="请选择部门" :options="departmentList" :props="{ checkStrictly: true, value: 'id' }" clearable style="width: 200px;" @change="showMonthNotWorkTime()"></el-cascader>
-                    <vueCascader :size="'small'" :widthStr="'200'" :clearable="true" :subject="departmentList" :radios="true" :distinction="'1'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1" :selectNameChuan="$t('other.allDepartments')" @change="showMonthNotWorkTime()"></vueCascader>
+                    <vueCascader :size="'small'" :widthStr="'200'" :clearable="true" :subject="trandepartmentList" :radios="true" :distinction="'15'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1" :selectNameChuan="$t('other.allDepartments')"></vueCascader>
                     <el-input style="width:200px;margin-left: 15px" v-if="user.userNameNeedTranslate != '1'" @keyup.enter.native="searchScreen(1)" v-model="searchKeyword" class="input-with-select" :placeholder="$t('defaultText.pleaseEnterNametoSearch')" clearable="true" size="small">
                         <el-button slot="append" @click="searchScreen(1)" icon="el-icon-search"></el-button>
                     </el-input>
@@ -1701,12 +1701,12 @@
             </div>
             <div>
                 <div style="margin-top:10px;">
+                    <el-cascader v-if="user.userNameNeedTranslate != 1" :size="'small'" v-model="deptIdForReminder" placeholder="请选择部门" :options="departmentList" :props="{ checkStrictly: true, value: 'id' }" clearable style="width: 200px;" @change="showMonthWorkTimeReminder()"></el-cascader>
+                    <vueCascader :size="'small'" :widthStr="'200'" :clearable="true" :subject="trandepartmentList" :radios="true" :distinction="'16'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1" :selectNameChuan="$t('other.allDepartments')"></vueCascader>
                     <el-input style="float:left;width:18%" v-if="user.userNameNeedTranslate != '1'" @keyup.enter.native="searchScreen(0)" v-model="searchKeyword" class="input-with-select" :placeholder="$t('defaultText.pleaseEnterNametoSearch')" clearable="true" size="small">
                         <el-button slot="append" @click="searchScreen(0)" icon="el-icon-search"></el-button>
                     </el-input>
                     <selectCat v-if="user.userNameNeedTranslate == '1'" :filterable="true"  :searchBoxTop="'1'" :size="'small'" :subject="usersList" :subjectId="usersListId" :distinction="'12'" :clearable="true" @selectCal="selectCal"></selectCat>
-                    <el-cascader v-if="user.userNameNeedTranslate != 1" :size="'small'" v-model="deptIdForReminder" placeholder="请选择部门" :options="departmentList" :props="{ checkStrictly: true, value: 'id' }" clearable style="width: 200px;" @change="showMonthWorkTimeReminder()"></el-cascader>
-                    <vueCascader :size="'small'" :widthStr="'200'" :clearable="true" :subject="departmentList" :radios="true" :distinction="'1'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1" :selectNameChuan="$t('other.allDepartments')" @change="showMonthWorkTimeReminder()"></vueCascader>
                     <el-checkbox v-model="isReminder" @change="showMonthWorkTimeReminder()">是否异常</el-checkbox>
                 </div>
             </div>
@@ -2430,6 +2430,7 @@
 
                 notifySelList:[],
                 departmentList: [],
+                trandepartmentList:[],
 
                 approvalProcessDialog: false,
                 approvalProcessData: [],
@@ -5288,6 +5289,7 @@
                         }
                         this.departmentList = JSON.parse(JSON.stringify(res.data))
                         var list = res.data , list1 = JSON.parse(JSON.stringify(res.data));
+                        this.trandepartmentList=this.changeArr(JSON.parse(JSON.stringify(res.data)))
                         // let noAllData = JSON.parse(JSON.stringify(res.data));
                         // if (this.user.role > 0) {
                             
@@ -8503,7 +8505,7 @@
                 this.workForm.domains[obj.idx].projectAuditorId = obj.id
             },
             vueCasader(obj) {
-                console.log(obj, '看看值')
+                console.log(obj, '看看值', this.departmentList)
                 if(obj.distinction == 1 && obj.item) {
                     let arr = []
                     arr.push(obj.item.value)
@@ -8514,6 +8516,24 @@
                     const { id, other } = obj
                     this.workForm.domains[other].reportTargetDeptId = id
                 }
+                if(obj.distinction == '14' && obj) {
+                    let arr = []
+                    arr.push(obj.id)
+                    this.deptIdForHasReport = arr
+                    this.showMonthWorkTime()
+                }
+                if(obj.distinction == '15' && obj) {
+                    let arr = []
+                    arr.push(obj.id)
+                    this.deptIdForNoReport = arr
+                    this.showMonthNotWorkTime()
+                }
+                if(obj.distinction == '16' && obj) {
+                    let arr = []
+                    arr.push(obj.id)
+                    this.deptIdForReminder = arr
+                    this.showMonthWorkTimeReminder()
+                }
             },
             //分页
             handleCurrentChange(val) {