Browse Source

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

zhouyy 5 months ago
parent
commit
468360a77a
28 changed files with 847 additions and 58 deletions
  1. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/index.html
  2. 7 0
      fhKeeper/formulahousekeeper/customerBuler-crm/logo.svg
  3. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm/src/assets/login/login_logo.png
  4. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm/src/assets/login/login_logos.png
  5. 17 15
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/business/index.vue
  6. 19 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contract/api.ts
  7. 136 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contract/component/addEditor.vue
  8. 499 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contract/index.vue
  9. 0 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contract/type.d.ts
  10. 9 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/home.vue
  11. 8 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/login.vue
  12. BIN
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/客户管家logo@3x.png
  13. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/type.d.ts
  14. 6 5
      fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/tools.ts
  15. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/vite.config.ts
  16. 27 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/BusinessOpportunityController.java
  17. 4 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/WeiXinCorpController.java
  18. 3 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/SysDict.java
  19. 1 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/ActionLogMapper.java
  20. 2 2
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ContractDocumentServiceImpl.java
  21. 7 10
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ContractServiceImpl.java
  22. 2 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SysFormServiceImpl.java
  23. 2 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SysRoleServiceImpl.java
  24. 3 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  25. 6 8
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/BusinessOpportunityMapper.xml
  26. 83 6
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/ContractMapper.xml
  27. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/i18n/messages.properties
  28. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/i18n/messages_en_US.properties

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/index.html

@@ -2,7 +2,7 @@
 
 <head>
   <meta charset="UTF-8" />
-  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
+  <link rel="icon" type="image/svg+xml" href="./logo.svg" />
   <meta name="viewport" content="width=device-width, initial-scale=1.0" />
   <title>客户管家</title>
 </head>

File diff suppressed because it is too large
+ 7 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/logo.svg


BIN
fhKeeper/formulahousekeeper/customerBuler-crm/src/assets/login/login_logo.png


BIN
fhKeeper/formulahousekeeper/customerBuler-crm/src/assets/login/login_logos.png


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

@@ -100,7 +100,7 @@
       </div>
     </div>
     <!-- 弹窗 -->
-    <el-dialog v-model="allVisible.newBusinessisible" width="1000" :show-close="false" top="10vh"
+    <el-dialog v-model="allVisible.newBusinessisible" width="1000" append-to-body :show-close="false" top="10vh"
       :before-close="handleClose">
       <template #header="{ close, titleId, titleClass }">
         <div class="flex justify-between items-center border-b pb-3 dialog-header">
@@ -298,24 +298,26 @@ function editBusiness(visibles: boolean) {
 }
 
 function editNewBusiness(item: any) {
-  console.log(item, '选择数据')
   showVisible('newBusinessisible')
-  allLoading.generateFormLading = true
-  if (item) {
-    editProduct(item)
-    businessTemplateValue.value = editBusinessData(item)
-    allText.newBusinessisibleText = '编辑商机'
-  }
-  if (!item) {
-    businessTemplateValue.value = {}
-    productTableListValue.value = []
-    allText.newBusinessisibleText = '新建商机'
-  }
   setTimeout(() => {
-    businessTemplateRef.value && businessTemplateRef.value.reset()
     businessTemplateKey.value++
+    if (item) {
+      allLoading.generateFormLading = true
+      editProduct(item)
+      businessTemplateValue.value = editBusinessData(item)
+      allText.newBusinessisibleText = '编辑商机'
+    }
+    if (!item) {
+      businessTemplateRef.value && businessTemplateRef.value.reset()
+      businessTemplate.value = businessTemplate.value
+      businessTemplateValue.value = {}
+      productTableListValue.value = []
+      allText.newBusinessisibleText = '新建商机'
+    }
+  }, 0)
+  setTimeout(() => {
     allLoading.generateFormLading = false
-  }, 500)
+  }, 700)
 }
 
 function newTask(item: any) {

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

@@ -0,0 +1,19 @@
+export const PATH = "/contract";
+export const GET_CONTRACT_TEMPLATE = "/sys-form/getListByCode" + PATH;
+export const OBTAIN_CONTRACT_TYPE = "/sys-dict/getListByCode?code=ContractType";
+export const ADD_CONTRACT = "/contract/addContract";
+export const EDIT_CONTRACT = "/contract/editContract";
+export const UPLOAD_ATTACHMENTS = "/contract-document/fileUpload";
+export const DELETE_CONTRACT_FILE = "/contract-document/fileDelete";
+export const GET_CONTRACT_LIST = "/contract/getContractPage";
+export const GET_PAYMENT_LIST = "/contract-payment/getList";
+export const CONTRACT_OPERATION = "/contract/processContract";
+export const CONTRACT_DELETION = "/contract/deleteContract";
+export const EXPORT_CONTRACT = "/contract/exportContract"
+export const IMPORITEM = "/contract/importContract"
+
+export const statusArray = [
+  { label: "审核通过", value: "0", color: "color:#67c23a;" },
+  { label: "待审核", value: "1", color: "color:#e6a23c;" },
+  { label: "已驳回", value: "2", color: "color:#f56c6c;" },
+];

+ 136 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contract/component/addEditor.vue

@@ -0,0 +1,136 @@
+<script lang="ts" setup>
+import { ref, reactive, onMounted, inject, watch } from "vue";
+import { UploadRequestOptions } from 'element-plus';
+import { Delete } from '@element-plus/icons-vue'
+import { tableShowOverflowTooltip } from '@/utils/globalVariables'
+import { formatDate } from '@/utils/times'
+import { downloadFile } from '@/utils/tools'
+import { post, get, uploadFile } from "@/utils/request";
+const props = defineProps<{
+  paymentPlan: any[],
+  enclosure: any[],
+  enclosureDetele: any[]
+}>()
+const globalPopup = inject<GlobalPopup>('globalPopup')
+const paymentPlan = ref(props.paymentPlan)
+const enclosure = ref(props.enclosure)
+const enclosureDetele = ref<any[]>([])
+const uploadRef = ref<any>()
+
+watch(() => props.paymentPlan, (newVal, _oldVal) => {
+  paymentPlan.value = newVal || []
+})
+
+watch(() => props.enclosure, (newVal, _oldVal) => {
+  enclosure.value = newVal || []
+})
+
+watch(() => props.enclosureDetele, (newVal, _oldVal) => {
+  enclosureDetele.value = newVal || []
+})
+
+// 上传附件
+async function httpUploadFile(param: UploadRequestOptions) {
+  const { file } = param
+  enclosure.value.push({ name: file.name, file, needUpload: true })
+  return
+}
+
+function addPlan() {
+  paymentPlan.value.push({
+    isPayed: false,
+    payDate: formatDate(new Date()),
+    amount: '0'
+  })
+}
+
+function deteleTables(row: any, index: number, type: 'paymentPlan' | 'enclosure') {
+  if (type === 'paymentPlan') {
+    paymentPlan.value.splice(index, 1)
+  } else {
+    if(row.id) {
+      enclosureDetele.value.push(row.id)
+    }
+    enclosure.value.splice(index, 1)
+  }
+}
+
+function getAddEditorData() {
+  return {
+    paymentPlan: paymentPlan.value,
+    enclosure: enclosure.value,
+    enclosureDetele: enclosureDetele.value
+  }
+}
+
+defineExpose({
+  getAddEditorData
+})
+
+</script>
+<template>
+  <div>
+    <div>回款计划</div>
+    <el-table :show-overflow-tooltip="tableShowOverflowTooltip" :data="paymentPlan" height="260">
+      <el-table-column label="是否已回款">
+        <template #default="scope">
+          <el-checkbox v-model="scope.row.isPayed" label="已回款" />
+        </template>
+      </el-table-column>
+      <el-table-column label="回款日期">
+        <template #default="scope">
+          <el-date-picker v-model="scope.row.payDate" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
+            placeholder="回款日期" />
+        </template>
+      </el-table-column>
+      <el-table-column label="汇款金额">
+        <template #default="scope">
+          <el-input v-model="scope.row.amount" v-enter-number placeholder="回款金额">
+            <template #prefix>
+              <el-text class="mx-1" type="info">¥</el-text>
+            </template>
+          </el-input>
+        </template>
+      </el-table-column>
+      <el-table-column prop="operation" width="80">
+        <template #header>
+          <el-link type="primary" :underline="false" @click="addPlan()">添加</el-link>
+        </template>
+        <template #default="scope">
+          <el-button type="danger" :icon="Delete" size="small"
+            @click="deteleTables(scope.row, scope.$index, 'paymentPlan')"></el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <div>附件</div>
+    <el-table :show-overflow-tooltip="tableShowOverflowTooltip" :data="enclosure" height="260">
+      <el-table-column label="序号" width="100">
+        <template #default="scope">
+          {{ scope.$index + 1 }}
+        </template>
+      </el-table-column>
+      <el-table-column label="文件名称" prop="name"></el-table-column>
+      <el-table-column label="操作" width="80">
+        <template #default="scope">
+          <el-link type="primary" :underline="false" v-if="scope.row.id" @click="downloadFile(scope.row.url, scope.row.name)">下载</el-link>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" width="80">
+        <template #header>
+          <el-upload ref="uploadRef" :http-request="httpUploadFile" :show-file-list="false" element-loading-text="正在上传"
+            multiple>
+            <template #trigger>
+              <el-link type="primary" :underline="false">添加</el-link>
+            </template>
+          </el-upload>
+        </template>
+        <template #default="scope">
+          <el-button type="danger" :icon="Delete" size="small"
+            @click="deteleTables(scope.row, scope.$index, 'enclosure')"></el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+<style lang="scss" scoped></style>

+ 499 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contract/index.vue

@@ -0,0 +1,499 @@
+<script lang="ts" setup>
+import { ref, reactive, onMounted, inject } from "vue";
+import { tableShowOverflowTooltip } from '@/utils/globalVariables'
+import { getFromValue, resetFromValue, setTemplateDataDisable, downloadFile, formatDate, confirmAction, getTemplateKey, downloadTemplate } from '@/utils/tools'
+import { GenerateForm } from '@zmjs/form-design';
+import { post, get, uploadFile } from "@/utils/request";
+import { CONTRACT_DELETION, CONTRACT_OPERATION, DELETE_CONTRACT_FILE, EDIT_CONTRACT, EXPORT_CONTRACT, GET_CONTRACT_LIST, GET_PAYMENT_LIST, IMPORITEM, OBTAIN_CONTRACT_TYPE, statusArray, UPLOAD_ATTACHMENTS } from './api'
+import { GET_CONTRACT_TEMPLATE, ADD_CONTRACT } from './api'
+import { UploadRequestOptions } from "element-plus";
+
+import AddEditor from "./component/addEditor.vue";
+
+const globalPopup = inject<GlobalPopup>('globalPopup')
+const filterContractForm = reactive({
+  name: '',
+  number: '',
+  typeName: '', // 合同类型
+  status: '',
+  startDate: '',
+  endDate: '',
+  paymentStartDate: '',
+  paymentEndDate: '',
+})
+const fixedData = reactive({
+  typeOfContractList: [] as optionType[],
+  stateList: statusArray as optionType[],
+})
+const allLoading = reactive({
+  exportLoading: false,
+  contractTableLading: false,
+  addEditorSaveLoading: false,
+  importLoading: false
+})
+const allVisable = reactive({
+  addEditorVisable: false,
+  rejectDataVisable: false,
+  importVisible: false
+})
+const allDynamicText = reactive({
+  addEditorText: '新增合同',
+  importText: '合同管理导入模板.xlsx'
+})
+const paging = reactive({
+  pageIndex: 1,
+  pageSize: 20,
+  pageTotal: 0
+})
+
+const contractTableList = ref<any>([]);
+const addEditorVisableForm = reactive({
+  paymentPlan: [],
+  enclosure: [],
+  enclosureDetele: []
+})
+
+const editForm = ref<any>({})
+const generateForm = ref<any>(null) // 模板
+const addEditorRef = ref<any>(null)
+const generateFormKey = ref<number>(1)
+const contractTemplate = ref<any>({
+  list: [] as any[],
+  config: {}
+})
+const rejectData = reactive({
+  id: '',
+  status: 2,
+  msg: '',
+})
+
+
+
+onMounted(() => {
+  getObtainContractType()
+  getTemplateConfig()
+  getContractTableList()
+})
+
+function contractRejection(row: any, status: number) {
+  rejectData.id = row.id
+  rejectData.status = status
+  rejectData.msg = ''
+  allVisable.rejectDataVisable = true
+}
+
+function deleteContract(row: any) {
+  confirmAction('确定要删除该合同吗?', '合同删除').then(() => {
+    post(CONTRACT_DELETION, { id: row.id }).then(() => {
+      globalPopup?.showSuccess('删除成功')
+      getContractTableList()
+    })
+  })
+}
+
+function contractApproved(row: any, status: number) {
+  confirmAction('确认审核通过吗?,通过后合同基本信息无法修改', '合同通过').then(() => {
+    contractOperation(row, status)
+  })
+}
+
+function rejectTheContract() {
+  confirmAction('确认驳回吗?,驳回后合同基本信息无法修改', '合同驳回').then(() => {
+    contractOperation(rejectData, 2)
+  })
+}
+
+async function importBusiness(param: UploadRequestOptions) {
+  allLoading.importLoading = true
+  const formData = new FormData();
+  formData.append('file', param.file)
+  formData.append('userId', sessionStorage.getItem('token') || '')
+  const res = await uploadFile(IMPORITEM, formData).finally(() => {
+    allLoading.importLoading = false
+  })
+  if (res.code == 'ok') {
+    globalPopup?.showSuccess('导入成功' || '')
+    getContractTableList()
+    return
+  }
+  globalPopup?.showError(res.msg || '')
+}
+
+function exportContract() {
+  allLoading.exportLoading = true
+  post(EXPORT_CONTRACT, {}).then((res) => {
+    downloadFile(res.data, '合同导出.xlsx')
+  }).finally(() => {
+    allLoading.exportLoading = false
+  })
+}
+
+async function addEditor(row?: any) {
+  allLoading.addEditorSaveLoading = false
+  editForm.value = row ? setEditForm(row) : {}
+  allDynamicText.addEditorText = row ? '编辑合同' : '新增合同'
+  contractTemplate.value.list = setTemplateDataDisable(contractTemplate.value.list, [...getTemplateKey(contractTemplate.value.list)], row?.status == 0)
+  generateFormKey.value++
+  setAddEditorVisableFormData(row)
+  if (row) {
+    const { data = [] } = await post(GET_PAYMENT_LIST, { contractId: row.id })
+    addEditorVisableForm.paymentPlan = data.map((item: any) => {
+      return {
+        isPayed: item.isPayed, amount: item.amount, payDate: item.payDate, id: item.id
+      }
+    })
+  }
+  allVisable.addEditorVisable = true
+}
+
+function setEditForm(row: any) {
+  const { id } = row
+  const filedList = getTemplateKey(contractTemplate.value.list)
+  const formFiled: any = {}
+  filedList.forEach((item: any) => {
+    formFiled[item] = row[item]
+  })
+  return {
+    ...formFiled, id
+  }
+}
+
+function setAddEditorVisableFormData(row: any) {
+  addEditorVisableForm.enclosureDetele = []
+  if (!row) {
+    addEditorVisableForm.paymentPlan = []
+    addEditorVisableForm.enclosure = []
+  }
+
+  if (row) {
+    const { files = [] } = row
+    addEditorVisableForm.enclosure = files.map((item: any) => {
+      return {
+        name: item.documentName,
+        id: item.id,
+        url: item.url
+      }
+    })
+  }
+}
+
+function resetFiltering() {
+  let newResetForm = resetFromValue(filterContractForm)
+  Object.assign(filterContractForm, newResetForm)
+}
+
+function contractOperation(row: any, status: number) {
+  let formVal = { status, id: row.id }
+  if (status == 2) {
+    formVal = row
+  }
+  post(CONTRACT_OPERATION, { ...formVal }).then(() => {
+    globalPopup?.showSuccess("操作成功")
+    if (status == 2) {
+      allVisable.rejectDataVisable = false
+    }
+    getContractTableList()
+  })
+}
+function getContractTableList() {
+  allLoading.contractTableLading = true
+  const formVal = getFromValue({ ...filterContractForm, pageIndex: paging.pageIndex, pageSize: paging.pageSize })
+  post(GET_CONTRACT_LIST, { ...formVal }).then((res) => {
+    // 赋值列表
+    const { total = 0, data = [] } = res.data
+    paging.pageTotal = total
+    contractTableList.value = data
+  }).finally(() => {
+    allLoading.contractTableLading = false
+  })
+}
+
+async function addEditorSave() {
+  const url = editForm.value.id ? EDIT_CONTRACT : ADD_CONTRACT
+  const data = await generateForm.value.getData()
+  const { paymentPlan = [], enclosure = [], enclosureDetele = [] } = addEditorRef.value.getAddEditorData()
+  let newPaymentPlan = paymentPlan
+  if (editForm.value.id) {
+    newPaymentPlan = paymentPlan.map((item: any) => { return { ...item, contractId: editForm.value.id } })
+  }
+
+  const formVal = getFromValue({
+    ...editForm.value,
+    ...data,
+    startDate: data.startDate ? formatDate(new Date(data.startDate)) : '',
+    endDate: data.endDate ? formatDate(new Date(data.endDate)) : '',
+    paymentListStr: JSON.stringify(newPaymentPlan)
+  })
+
+  let totalAmount = 0
+  // 判断
+  for(let i in paymentPlan) {
+    if(!paymentPlan[i].payDate) {
+      globalPopup?.showWarning('回款日期不能为空')
+      return
+    }
+
+    if(!paymentPlan[i].amount || paymentPlan[i].amount == 0) {
+      globalPopup?.showWarning('回款金额不能为空和0')
+      return
+    }
+
+    totalAmount += +paymentPlan[i].amount || 0
+  }
+
+  if(totalAmount > +(formVal.amounts || 0)) {
+    globalPopup?.showWarning('总回款金额不得大于合同金额')
+    return
+  }
+
+  allLoading.addEditorSaveLoading = true
+  post(url, { ...formVal }).then((res) => {
+    if (enclosure.length > 0) {
+      fileUpload(String(res.data || editForm.value.id), enclosure)
+    }
+    if (enclosureDetele.length > 0) {
+      fileUploadDetele(String(res.data || editForm.value.id), enclosureDetele)
+    }
+    if(enclosure.length == 0) {
+      allLoading.addEditorSaveLoading = false
+      globalPopup?.showSuccess('添加成功')
+      allVisable.addEditorVisable = false
+      getContractTableList()
+    }
+  }).catch(() => {
+    allVisable.addEditorVisable = false
+  })
+}
+
+function fileUpload(id: string, enclosure = []) {
+  const formData = new FormData()
+  formData.append('ContractId', id);
+  enclosure.forEach((item: any) => {
+    if (item.needUpload) {
+      formData.append('file', item.file);
+    }
+  });
+  post(UPLOAD_ATTACHMENTS, formData).then(re => {
+    globalPopup?.showSuccess(re.msg)
+    getContractTableList()
+  }).finally(() => {
+    allVisable.addEditorVisable = false
+  })
+}
+
+function fileUploadDetele(id: string, enclosureDetele = []) {
+  post(DELETE_CONTRACT_FILE, { contractId: id, fileIds: enclosureDetele.join(',') })
+}
+
+function handleSizeChange(val: number) {
+  paging.pageIndex = 1
+  paging.pageSize = val
+  getContractTableList()
+}
+
+function handleCurrentChange(val: number) {
+  paging.pageIndex = val
+  getContractTableList()
+}
+
+function getTemplateConfig() {
+  get(GET_CONTRACT_TEMPLATE).then(res => {
+    const datas = JSON.parse(res.data[0] && res.data[0].config)
+    contractTemplate.value = datas
+  })
+}
+
+function getObtainContractType() {
+  get(OBTAIN_CONTRACT_TYPE).then(res => {
+    const list = res.data || []
+    fixedData.typeOfContractList = list.map((item: any) => {
+      return {
+        label: item.name,
+        value: item.id
+      }
+    })
+  })
+}
+</script>
+
+<template>
+  <div class="h-full flex">
+    <div class="p-5 w-80 pr-0">
+      <div class="bg-white w-full h-full shadow-md rounded-md flex flex-col">
+        <div class="flex-1 p-3 overflow-y-auto">
+          <el-form :model="filterContractForm" label-width="100px" style="max-width: 600px">
+            <el-form-item label="合同编号">
+              <el-input v-model="filterContractForm.number" clearable placeholder="请输入"></el-input>
+            </el-form-item>
+            <el-form-item label="合同类型">
+              <el-select v-model="filterContractForm.typeName" placeholder="请选择" clearable filterable>
+                <el-option v-for="item in fixedData.typeOfContractList" :key="item.value" :label="item.label"
+                  :value="item.value" />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="状态">
+              <el-select v-model="filterContractForm.status" placeholder="请选择" clearable filterable>
+                <el-option v-for="item in fixedData.stateList" :key="item.value" :label="item.label"
+                  :value="item.value" />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="创建时间">
+              <el-date-picker v-model="filterContractForm.startDate" type="date" placeholder="请选择" :clearable="false"
+                format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
+            </el-form-item>
+            <el-form-item label="">
+              <el-date-picker v-model="filterContractForm.endDate" type="date" placeholder="请选择" :clearable="false"
+                format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
+            </el-form-item>
+            <el-form-item label="下笔回款日期">
+              <el-date-picker v-model="filterContractForm.paymentStartDate" type="date" placeholder="请选择"
+                :clearable="false" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
+            </el-form-item>
+            <el-form-item label="">
+              <el-date-picker v-model="filterContractForm.paymentEndDate" type="date" placeholder="请选择"
+                :clearable="false" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
+            </el-form-item>
+          </el-form>
+        </div>
+        <div class="w-full flex p-3 shadow-[0_-3px_5px_0px_rgba(0,0,0,0.2)]">
+          <El-button class="w-full" @click="resetFiltering()">重置</El-Button>
+          <El-button type="primary" class="w-full" :loading="allLoading.contractTableLading"
+            @click="getContractTableList()">搜索</El-Button>
+        </div>
+      </div>
+    </div>
+    <div class="flex-1 p-5 overflow-auto">
+      <div class="bg-white w-full h-full p-3 shadow-md rounded-md flex flex-col">
+        <div class="flex justify-end pb-3">
+          <el-button type="primary" v-permission="['contractAdd']" @click="addEditor()">新增合同</el-button>
+          <el-button type="primary" v-permission="['contractImport']" @click="allVisable.importVisible = true">导入</el-button>
+          <el-button type="primary" v-permission="['contractExport']" :loading="allLoading.exportLoading"
+            @click="exportContract()">导出</el-button>
+        </div>
+        <div class="flex-1 w-full overflow-hidden">
+          <el-table ref="contractTableRef" :show-overflow-tooltip="tableShowOverflowTooltip" :data="contractTableList"
+            border v-loading="allLoading.contractTableLading" style="width: 100%;height: 100%;">
+            <el-table-column prop="number" label="合同编号" width="180"></el-table-column>
+            <el-table-column prop="name" label="合同名称" width="180"></el-table-column>
+            <el-table-column prop="amounts" label="合同金额" width="180">
+              <template #default="scope">
+                ¥ {{ scope.row.amounts ? scope.row.amounts.toFixed(2) : '0.00' }}
+              </template>
+            </el-table-column>
+            <el-table-column prop="payment" label="已回款金额" width="180">
+              <template #default="scope">
+                ¥ {{ scope.row.payment ? scope.row.payment.toFixed(2) : '0.00' }}
+              </template>
+            </el-table-column>
+            <el-table-column prop="payment" label="已回款进度" width="180">
+              <template #default="scope">
+                {{ scope.row.payment ? (100 * scope.row.payment / scope.row.amounts).toFixed(1) + '%' : '0%' }}
+              </template>
+            </el-table-column>
+            <el-table-column prop="nextPaymentDate" label="下笔回款日期" width="180">
+              <template #default="scope">
+                {{ scope.row.nextPaymentDate ? scope.row.nextPaymentDate : '-' }}
+              </template>
+            </el-table-column>
+            <el-table-column prop="nextPaymentAmount" label="下笔回款金额" width="180">
+              <template #default="scope">
+                {{ scope.row.nextPaymentAmount ? '¥' + scope.row.nextPaymentAmount.toFixed(2) : '-' }}
+              </template>
+            </el-table-column>
+            <el-table-column prop="typeName" label="合同类型" width="180"></el-table-column>
+            <el-table-column prop="name" label="状态" width="180">
+              <template #default="scope">
+                <span :style="fixedData.stateList[scope.row.status].color">{{
+                  fixedData.stateList[scope.row.status].label }}</span>
+              </template>
+            </el-table-column>
+            <el-table-column prop="indate" label="创建时间" width="180"></el-table-column>
+            <el-table-column label="操作" fixed="right" width="200" v-permission="['contractAdd', 'auditContractData']">
+              <template #default="scope">
+                <el-button link type="primary" size="large" v-permission="['contractAdd']"
+                  @click="addEditor(scope.row)">编辑</el-button>
+                <el-button link type="success" size="large" v-permission="['auditContractData']"
+                  v-if="(scope.row.status == 1 || scope.row.status == 3)"
+                  @click="contractApproved(scope.row, 0)">通过</el-button>
+                <el-button link type="danger" size="large" v-permission="['auditContractData']"
+                  v-if="(scope.row.status == 1 || scope.row.status == 3)"
+                  @click="contractRejection(scope.row, 2)">驳回</el-button>
+                <el-button link type="danger" size="large" v-permission="['contractAdd']"
+                  @click="deleteContract(scope.row)">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+        <div class="flex justify-end pt-3">
+          <el-pagination layout="total, prev, pager, next, sizes" v-model:current-page="paging.pageIndex"
+            v-model:page-size="paging.pageSize" :page-sizes="[10, 20, 30, 50, 100]" @size-change="handleSizeChange"
+            @current-change="handleCurrentChange" :total="paging.pageTotal" />
+        </div>
+      </div>
+    </div>
+
+    <!-- 弹窗 -->
+    <el-dialog v-model="allVisable.addEditorVisable" 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">{{ allDynamicText.addEditorText }}</h4>
+          <div>
+            <el-button type="primary" :loading="allLoading.addEditorSaveLoading" @click="addEditorSave">保存</el-button>
+            <el-button @click="allVisable.addEditorVisable = false">取消</el-button>
+          </div>
+        </div>
+      </template>
+      <div class="h-[60vh] overflow-y-auto scroll-bar pt-3">
+        <div class="ml-4 mr-4">
+          <GenerateForm ref="generateForm" :data="contractTemplate" :value="editForm" :key="generateFormKey" />
+          <AddEditor ref="addEditorRef" :payment-plan="addEditorVisableForm.paymentPlan"
+            :enclosure="addEditorVisableForm.enclosure" :enclosure-detele="addEditorVisableForm.enclosureDetele">
+          </AddEditor>
+        </div>
+      </div>
+    </el-dialog>
+
+    <el-dialog v-model="allVisable.rejectDataVisable" 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="rejectTheContract">驳回</el-button>
+            <el-button @click="allVisable.rejectDataVisable = false">取消</el-button>
+          </div>
+        </div>
+      </template>
+      <div class="overflow-y-auto scroll-bar pt-3">
+        <div class="ml-4 mr-4">
+          <el-input v-model="rejectData.msg" style="width: 100%" :autosize="{ minRows: 6, maxRows: 6 }" type="textarea"
+            placeholder="请输入驳回原因" />
+        </div>
+      </div>
+    </el-dialog>
+
+    <!-- 导入 -->
+    <el-dialog v-model="allVisable.importVisible" width="680" :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 class="flex">
+            <el-upload class="upload-demo mr-3" :limit="1" :show-file-list="false" accept=".xlsx"
+              :http-request="importBusiness">
+              <el-button type="primary" :loading="allLoading.importLoading">导入</el-button>
+            </el-upload>
+            <el-button @click="allVisable.importVisible = false">取消</el-button>
+          </div>
+        </div>
+      </template>
+      <div class="p-8">
+        <div class="ml-4 mr-4">
+          <div class="flex items-center">1、点击下载 <el-link type="primary"
+              @click="downloadTemplate('Contract', allDynamicText.importText)">{{ allDynamicText.importText }}</el-link></div>
+          <div class="mt-4">2、填写合同名称必填</div>
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<style lang="scss" scoped></style>

+ 0 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/contract/type.d.ts


+ 9 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/home.vue

@@ -6,7 +6,7 @@
       </el-header>
       <el-main>
         <router-view v-slot="{ Component }">
-          <transition name="router_animate">
+          <transition name="ranimate">
             <component :is="Component" />
           </transition>
         </router-view>
@@ -95,4 +95,12 @@ onMounted(async () => {
   overflow: auto;
   background: $backColor;
 }
+
+.ranimate-enter-active {
+  animation: fadeIn .6s;
+}
+
+.ranimate-leave-active {
+  animation: fadeOut .3s;
+}
 </style>

+ 8 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/login.vue

@@ -20,7 +20,7 @@
         </div>
       </el-form>
       <el-divider content-position="center">或</el-divider>
-      <div class="m-auto mb-5">
+      <div class="m-auto mb-5" @click="wxworkCli()">
         <img class="w-9 m-auto p-1 rounded-full border-blue-300 border-2 cursor-pointer" :src="qiyeweixin" alt="">
       </div>
       <div class="flex justify-between pb-5">
@@ -197,6 +197,13 @@ const tryAutoLogin = () => {
   var weixinUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appId + "&redirect_uri=" + encodeURI(url) + "&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
   window.location.href = weixinUrl;
 }
+const wxworkCli = () => {
+    var appId = "wwdd1137a65ce0fc87";//企业微信第三方的SUIT ID
+    var url = "https://crm.ttkuaiban.com/api/corpWXScanningAuth";//授权回调页面
+    // var weixinUrl=`https://open.work.weixin.qq.com/wwopen/sso/3rd_qrConnect?appid=${appId}&redirect_uri=${url}&state=0&usertype=member`;
+    var weixinUrl=`https://login.work.weixin.qq.com/wwlogin/sso/login?login_type=ServiceApp&appid=${appId}&redirect_uri=${url}&state=0`;
+    window.location.href = weixinUrl;
+}
 
 onMounted(() => {
   checkLogin()

BIN
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/客户管家logo@3x.png


+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/type.d.ts

@@ -38,7 +38,7 @@ type componentType = "success" | "info" | "warning" | "error"
 
 type TaskResponse = { saveLoading: saveLoadingType, isClose: boolean, message?: string }
 
-type optionType = { value: number | string, label: string | number }
+type optionType = { value: number | string, label: string | number, color?: string }
 
 type sexTYpe = { value: number | string, label: string }
 

+ 6 - 5
fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/tools.ts

@@ -240,25 +240,26 @@ export function getTemplateKey(list: Array<any>) {
 }
 
 /**
- * 设置模板数据禁用
+ * 设置模板数据禁用和启用
  * @param list 模板数据
- * @param fieldList 需要禁用的字段
+ * @param fieldList 需要操作的字段
+ * @param filedFlag Boolean
  * @returns 
  */
-export function setTemplateDataDisable(list: Array<any>, fieldList: Array<any>) {
+export function setTemplateDataDisable(list: Array<any>, fieldList: Array<any>, filedFlag: boolean = true) {
   let result = list;
   result.forEach((item: any) => {
     if (item.type === 'grid') {
       item.columns.forEach((column: any) => {
         column.list.forEach((subItem: any) => {
           if (fieldList.includes(subItem.model)) {
-            subItem.options.disabled = true
+            subItem.options.disabled = filedFlag
           }
         });
       });
     } else {
       if (fieldList.includes(item.model)) {
-        item.options.disabled = true;
+        item.options.disabled = filedFlag;
       }
     }
   })

+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/vite.config.ts

@@ -4,8 +4,8 @@ import vue from '@vitejs/plugin-vue';
 import { resolve } from 'path';
 
 // const target = 'http://192.168.2.28:10010';
-// const target = 'http://192.168.2.17:10010';
-const target = "http://127.0.0.1:10010";
+const target = 'http://192.168.2.17:10010';
+// const target = "http://127.0.0.1:10010";
 // const target = "http://192.168.2.178:10010";
 // const target = 'http://47.101.180.183:10010';
 

+ 27 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/BusinessOpportunityController.java

@@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.text.SimpleDateFormat;
 import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -318,6 +319,32 @@ public class BusinessOpportunityController {
         msg.setData(r);
         return msg;
 
+    }
+
+    @RequestMapping("getAllByStage")
+    public Object getAllByStage(HttpServletRequest request) {
+        User user = userMapper.selectById(request.getHeader("Token"));
+        List<BusinessOpportunity> list = new ArrayList<>();
+        boolean isAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部商机");
+        boolean isNotAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看负责部门商机");
+        if (isAll) {
+            list = boMapper.getAllList(user.getCompanyId());
+        } else if (isNotAll) {
+            list = boMapper.getAllList1(user);
+        } else {
+            list = boMapper.getAllList2(user);
+        }
+        HttpRespMsg msg = new HttpRespMsg();
+        List<Stage> stageList = stageService.list(new QueryWrapper<Stage>().eq("company_id", user.getCompanyId()));
+        HashMap<String, Object> map = new HashMap<>();
+        for (Stage stage : stageList) {
+            List<BusinessOpportunity> collect = list.stream().filter(l -> l.getStageId() != null && l.getStageId().equals(stage.getId())).collect(Collectors.toList());
+            HashMap<String, Object> hashMap = new HashMap<>();
+            map.put(stage.getName(),collect);
+        }
+        msg.setData(map);
+        return msg;
+
     }
     @RequestMapping("deleterList")
     public HttpRespMsg deleterList(BusinessOpportunity bo, HttpServletRequest request) {

File diff suppressed because it is too large
+ 4 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/WeiXinCorpController.java


+ 3 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/SysDict.java

@@ -59,7 +59,7 @@ public class SysDict extends Model<SysDict> {
         return this.id;
     }
 
-    public static final String[] TYPE_LIST=new String[]{"ClueSources","CustomLevel","CustomIndustry","CustomSources","BusinessStage","ProductType","ProductUnit","OrderType"};
+    public static final String[] TYPE_LIST=new String[]{"ClueSources","CustomLevel","CustomIndustry","CustomSources","BusinessStage","ProductType","ProductUnit","OrderType","ContractType"};
 
     public static List<Map<String,Object>> getSysDictList(){
         List<Map<String,Object>> itemList=new ArrayList<>();
@@ -83,6 +83,8 @@ public class SysDict extends Model<SysDict> {
                     break;
                 case "OrderType":map.put("name","订单类型");
                     break;
+                case "ContractType":map.put("name","合同类型");
+                    break;
             }
             itemList.add(map);
         }

+ 1 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/ActionLogMapper.java

@@ -19,7 +19,7 @@ public interface ActionLogMapper extends BaseMapper<ActionLog> {
 
     @Select("select a.*,u.`name` userName from action_log a left join `user` u on a.user_id = u.id where code = 'clue' and item_id = #{id}")
     List<ActionLog> selectByInfoList(Integer id);
-    @Select("select a.*,u.`name` userName from action_log a left join `user` u on a.user_id = u.id where code = 'business' and item_id = #{id}")
+    @Select("select a.*,u.`name` userName from action_log a left join `user` u on a.user_id = u.id where code = 'business' and item_id = #{id} order by creat_time desc")
     List<ActionLog> selectByInfoListBusiness(Integer id);
     @Select("select a.*,u.`name` userName from action_log a left join `user` u on a.user_id = u.id where code = 'custom' and item_id = #{id}")
     List<ActionLog> selectByInfoListCustom(Integer id);

+ 2 - 2
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ContractDocumentServiceImpl.java

@@ -63,7 +63,7 @@ public class ContractDocumentServiceImpl extends ServiceImpl<ContractDocumentMap
     public HttpRespMsg fileUpload(HttpServletRequest request, @RequestParam Integer ContractId, @RequestParam(required=false) Integer folderId, @RequestParam("file") MultipartFile[] files) {
         HttpRespMsg msg = new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
-        List<SysRichFunction> functionContractList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "管理全部合同");
+        List<SysRichFunction> functionContractList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "查看全部合同");
         if(functionContractList.size() <= 0){
             msg.setError(MessageUtils.message("access.operationError"));
             return msg;
@@ -205,7 +205,7 @@ public class ContractDocumentServiceImpl extends ServiceImpl<ContractDocumentMap
     public HttpRespMsg fileDelete(HttpServletRequest request, ContractFileDelVO contractFileDelVo) {
         HttpRespMsg msg = new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("Token"));
-        List<SysRichFunction> functionContractList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "管理全部合同");
+        List<SysRichFunction> functionContractList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "查看全部合同");
         if(functionContractList.size() <= 0){
             msg.setError(MessageUtils.message("access.deleteError"));
             return msg;

+ 7 - 10
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ContractServiceImpl.java

@@ -80,8 +80,6 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
     private ContractLogMapper contractLogMapper;
     @Resource
     private InformationMapper informationMapper;
-    @Resource
-    private CompanyDingdingMapper companyDingdingMapper;
     @Value(value = "${upload.path}")
     private String path;
     @Autowired
@@ -111,7 +109,6 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
             String token = request.getHeader("token");
             User user = userMapper.selectById(token);
             WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
-            CompanyDingding dingding = companyDingdingMapper.selectOne(new LambdaQueryWrapper<CompanyDingding>().eq(CompanyDingding::getCompanyId, user.getCompanyId()));
             List<SysRichFunction> functionContractList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "查看全部合同");
             if(functionContractList.size() <= 0){
                 httpRespMsg.setError(MessageUtils.message("access.viewError"));
@@ -193,14 +190,17 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
                 contractPageVO.setPayment(contract.getPayment());
                 contractPageVO.setNextPaymentDate(contract.getNextPaymentDate());
                 contractPageVO.setNextPaymentAmount(contract.getNextPaymentAmount());
+                contractPageVO.setPlate1(contract.getPlate1());
+                contractPageVO.setPlate2(contract.getPlate2());
+                contractPageVO.setPlate3(contract.getPlate3());
+                contractPageVO.setPlate4(contract.getPlate4());
+                contractPageVO.setPlate5(contract.getPlate5());
                 if (contract.getStatus().equals(2)){
                     for (Map<String, Object> contractLog : contractLogs) {
                         if (contractLog.get("contractId").toString().equals(contract.getId().toString())){
                             String msg = "";
                             if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
                                 msg = "$userName=" + contractLog.get("operateCorpWxId") + "$" + contractLog.get("msg");
-                            }else if(dingding!=null&&dingding.getContactNeedTranslate()==1){
-                                msg = "$userName=" + contractLog.get("operateName") + "$" + contractLog.get("msg");
                             }else {
                                 msg = contractLog.get("operateName") + "" + contractLog.get("msg");
                             }
@@ -256,7 +256,6 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
             return httpRespMsg;
         }
         WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", user.getCompanyId()));
-        CompanyDingding dingding = companyDingdingMapper.selectOne(new QueryWrapper<CompanyDingding>().eq("company_id", user.getCompanyId()));
         HttpRespMsg contractPage = getContractPage(request, null, null, number, name, typeName, status, startDate, endDate, paymentStartDate, paymentEndDate, secTypeId,customerOrg,finishStatus);
         HashMap<String, Object> resultDate = (HashMap<String, Object>) contractPage.data;
         List<ContractPageVO> data = (List<ContractPageVO>)resultDate.get("data");
@@ -291,8 +290,6 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
             item.add(contract.getEndDate()==null?"":contract.getEndDate()+"");
             if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
                 contract.setCreatorName("$userName=" + contract.getCreatorWxCorpId() + "$");
-            }else if(dingding!=null&&dingding.getContactNeedTranslate()==1){
-                contract.setCreatorName("$userName=" + contract.getCreatorName() + "$");
             }else {
                 contract.setCreatorName(contract.getCreatorName());
             }
@@ -426,7 +423,7 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
     public HttpRespMsg editContract(HttpServletRequest request, Contract contract, ContractCustom custom, String paymentListStr) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
-        List<SysRichFunction> functionContractList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "管理全部合同");
+        List<SysRichFunction> functionContractList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "查看全部合同");
         if(functionContractList.size() <= 0){
             httpRespMsg.setError(MessageUtils.message("access.operationError"));
             return httpRespMsg;
@@ -1149,7 +1146,7 @@ public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> i
         HttpRespMsg msg = new HttpRespMsg();
         String token = request.getHeader("TOKEN");
         User user = userMapper.selectById(token);
-        List<SysRichFunction> functionContractList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "管理全部合同");
+        List<SysRichFunction> functionContractList = sysFunctionMapper.getRoleFunctions(user.getRoleId(), "查看全部合同");
         if(functionContractList.size() <= 0){
             msg.setError(MessageUtils.message("access.deleteError"));
             return msg;

+ 2 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SysFormServiceImpl.java

@@ -105,6 +105,8 @@ public class SysFormServiceImpl extends ServiceImpl<SysFormMapper, SysForm> impl
                 break;
             case "Business":title = company.getCompanyName()+"_商机导入模板";
                 break;
+            case "Contract":title = company.getCompanyName()+"_合同导入模板";
+                break;
             default:title="";
         }
         String result=MessageUtils.message("file.excelScu");

+ 2 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SysRoleServiceImpl.java

@@ -82,7 +82,8 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> impl
             "负责部门线索数据","全部线索数据","负责部门商机数据","全部商机数据",
             "负责部门销售数据","全部销售数据","负责部门任务数据","全部任务数据",
             "查看全部产品数据","查看负责部门产品数据",
-            "查看负责部门订单","查看全部订单"
+            "查看负责部门订单","查看全部订单",
+            "查看全部合同","审核合同","新增合同","合同类型管理","导入合同","导出合同"
             };
     public static final HashMap<String, String[]> functionMaps = new HashMap();
     static {

File diff suppressed because it is too large
+ 3 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/UserServiceImpl.java


+ 6 - 8
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/BusinessOpportunityMapper.xml

@@ -279,32 +279,30 @@
         GROUP BY s.id
     </select>
     <select id="getAllList" resultType="com.management.platform.entity.BusinessOpportunity">
-        select
-        id,
-        name
+        select *
         from business_opportunity
         where company_id = #{companyId}
         and is_delete = 0
+        order by create_time desc
     </select>
 
     <select id="getAllList1" resultType="com.management.platform.entity.BusinessOpportunity">
-        select
-        id,
-        name
+        select *
         from business_opportunity
         where company_id = #{companyId}
         and is_delete = 0
         and (incharger_id in
         (SELECT id from `user` WHERE department_id = (SELECT department_id from `user` WHERe id = #{id}))
         or incharger_id is null)
+        order by create_time desc
     </select>
 
     <select id="getAllList2" resultType="com.management.platform.entity.BusinessOpportunity">
-        select id,
-               name
+        select *
         from business_opportunity
         where company_id = #{companyId}
           and is_delete = 0
           and (incharger_id = #{id} or incharger_id is null)
+        order by create_time desc
     </select>
 </mapper>

+ 83 - 6
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/ContractMapper.xml

@@ -20,16 +20,93 @@
         <result column="remarks" property="remarks" />
         <result column="payment" property="payment" />
         <result column="sec_type_id" property="secTypeId" />
-        <result column="plate1" property="plate1" />
-        <result column="plate2" property="plate2" />
-        <result column="plate3" property="plate3" />
-        <result column="plate4" property="plate4" />
-        <result column="plate5" property="plate5" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, company_id, creator_id, start_date, end_date, number, project_id, name, amounts, type_id, checkerId, status, indate, remarks, payment, sec_type_id, plate1, plate2, plate3, plate4, plate5
+        id, company_id, creator_id, start_date, end_date, number, project_id, name, amounts, type_id, checkerId, status, indate, remarks, payment, sec_type_id
     </sql>
+    <select id="selectContract" resultType="com.management.platform.entity.Contract">
+        select contract.id,contract.company_id,contract.creator_id,contract.number,contract.name,contract.amounts,contract.type_id,sys_dict.name typeName,contract.status,contract.indate,contract.remarks,
+        contract.start_date as startDate,contract.end_date as endDate,contract_type_sec.sec_type_name,contract.sec_type_id,
+        user.name as creatorName,user.corpwx_userid as creatorWxCorpId, contract.project_id, contract.payment, cp.pay_date AS next_payment_date, cp.amount AS next_payment_amount,
+        contract.plate1,contract.plate2,contract.plate3,contract.plate4,contract.plate5
+        from contract
+        left join sys_dict on contract.type_id = sys_dict.id
+        left join contract_type_sec on contract.sec_type_id = contract_type_sec.id
+        LEFT JOIN (SELECT contract_id, pay_date, amount FROM contract_payment WHERE is_payed = 0 GROUP BY contract_id) cp ON cp.contract_id=contract.id
+        left join user
+        on contract.creator_id = user.id
+        left join contract_custom cc on cc.contract_id=contract.id
+        where contract.company_id = #{companyId}
+        <if test="number!=null">
+            and number like CONCAT('%', #{number}, '%')
+        </if>
+        <if test="name!=null">
+            and contract.name like CONCAT('%', #{name}, '%')
+        </if>
+        <if test="typeName!=null">
+            and sys_dict.name = #{typeName}
+        </if>
+        <if test="secTypeId!=null">
+            and contract.sec_type_id = #{secTypeId}
+        </if>
+        <if test="status!=null">
+            and status = #{status}
+        </if>
+        <if test="startDate!=null and endDate !=null">
+            and indate between #{startDate} and #{endDate}
+        </if>
+        <if test="paymentStartDate != null and paymentEndDate != null">
+            and cp.pay_date between #{paymentStartDate} and #{paymentEndDate}
+        </if>
+        <if test="finishStatus!=null">
+            and cc.finish_status = #{finishStatus}
+        </if>
+        <if test="customerOrg!=null">
+            and cc.customer_org like  CONCAT('%', #{customerOrg}, '%')
+        </if>
+        order by contract.number desc
+        <if test="pageStart!=null and pageSize!=null">
+            limit #{pageStart},#{pageSize}
+        </if>
+    </select>
 
+    <select id="selectContractCnt" resultType="java.lang.Long">
+        select count(1) from contract
+        left join contract_type
+        on contract.type_id = contract_type.id
+        LEFT JOIN (SELECT contract_id, pay_date, amount FROM contract_payment WHERE is_payed = 0 GROUP BY contract_id) cp ON cp.contract_id=contract.id
+        left join user
+        on contract.creator_id = user.id
+        left join contract_custom cc on cc.contract_id=contract.id
+        where contract.company_id = #{companyId}
+        <if test="number!=null">
+            and number like CONCAT('%', #{number}, '%')
+        </if>
+        <if test="name!=null">
+            and contract.name like CONCAT('%', #{name}, '%')
+        </if>
+        <if test="typeName!=null">
+            and contract_type.id = #{typeName}
+        </if>
+        <if test="secTypeId!=null">
+            and contract.sec_type_id = #{secTypeId}
+        </if>
+        <if test="status!=null">
+            and status = #{status}
+        </if>
+        <if test="startDate!=null and endDate !=null">
+            and indate between #{startDate} and #{endDate}
+        </if>
+        <if test="paymentStartDate != null and paymentEndDate != null">
+            and cp.pay_date between #{paymentStartDate} and #{paymentEndDate}
+        </if>
+        <if test="finishStatus!=null">
+            and cc.finish_status = #{finishStatus}
+        </if>
+        <if test="customerOrg!=null">
+            and cc.customer_org like  CONCAT('%', #{customerOrg}, '%')
+        </if>
+    </select>
 </mapper>

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/i18n/messages.properties

@@ -158,7 +158,7 @@ finance.skipData=跳过以下已审核数据:{0}。
 finance.importErrorByAllAdopt=本次数据全部已审核通过,无法导入。
 finance.review=专业审核
 finance.dept=部门审核
-finance.hasApprovedReport=已存在审核人审核通过,无法撤回。请联系管理员操作
+finance.hasApprovedReport=请联系审核人撤销审核后修改
 # pdf相关
 pdf.previewError=该格式不支持在线预览
 # 日报相关

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/i18n/messages_en_US.properties

@@ -158,7 +158,7 @@ finance.skipData=Skipping the following audited data: '{0}'.
 finance.importErrorByAllAdopt=This data has been approved and cannot be imported.
 finance.review=Professional review
 finance.dept=Department review
-finance.hasApprovedReport=Some daily reports have been approved, unable to operate. Please contact your system manager.
+finance.hasApprovedReport=Please contact the auditor to reject your report.
 # pdf相关
 pdf.previewError=This format does not support online preview.
 # 日报相关