Przeglądaj źródła

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

hlp 1 rok temu
rodzic
commit
c29e2ce23a
100 zmienionych plików z 38247 dodań i 16431 usunięć
  1. 1 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/components/TaskModal/index.vue
  2. 8 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/api.ts
  3. 76 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/attachment.vue
  4. 73 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/information.vue
  5. 58 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/operationRecord.vue
  6. 93 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/products.vue
  7. 81 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/relatedBusiness.vue
  8. 92 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/relatedProducts.vue
  9. 152 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/detail/index.vue
  10. 264 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/index.vue
  11. 11 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/type.d.ts
  12. 2 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/system/customForm/index.vue
  13. 9 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/constant.ts
  14. 118 45
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/components/attachment.vue
  15. 208 17
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/components/information.vue
  16. 18 35
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/components/operationRecord.vue
  17. 40 5
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/index.vue
  18. 166 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/deteleTables.vue
  19. 222 28
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/index.vue
  20. 2 2
      fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/type.d.ts
  21. 3 1
      fhKeeper/formulahousekeeper/customerBuler-crm/src/type.d.ts
  22. 31 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/times.ts
  23. 55 0
      fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/tools.ts
  24. 33330 16130
      fhKeeper/formulahousekeeper/management-crm/crm.log
  25. 21 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ActionLogController.java
  26. 21 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/BusinessItemCustomController.java
  27. 109 12
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/BusinessOpportunityController.java
  28. 21 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/BusinessProductController.java
  29. 102 26
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ClueController.java
  30. 21 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ClueUploadfileController.java
  31. 134 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/CustomController.java
  32. 21 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/CustomItemContactsController.java
  33. 89 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/OrderController.java
  34. 21 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/OrderProductDetailController.java
  35. 21 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/SeqController.java
  36. 21 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/StageController.java
  37. 10 5
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/TaskController.java
  38. 21 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/UploadFileController.java
  39. 71 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/ActionLog.java
  40. 48 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/BusinessItemCustom.java
  41. 10 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/BusinessItemProduct.java
  42. 42 9
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/BusinessOpportunity.java
  43. 73 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/BusinessProduct.java
  44. 23 6
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Clue.java
  45. 68 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/ClueUploadfile.java
  46. 6 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Contacts.java
  47. 59 6
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Custom.java
  48. 48 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/CustomItemContacts.java
  49. 76 2
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Order.java
  50. 58 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/OrderProductDetail.java
  51. 7 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Product.java
  52. 59 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Seq.java
  53. 60 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Stage.java
  54. 15 9
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Task.java
  55. 4 1
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/TaskExecutor.java
  56. 7 2
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/TaskLog.java
  57. 84 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/UploadFile.java
  58. 18 6
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/vo/TasKVo.java
  59. 22 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/ActionLogMapper.java
  60. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/BusinessItemCustomMapper.java
  61. 3 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/BusinessItemProductMapper.java
  62. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/BusinessProductMapper.java
  63. 10 2
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/ClueMapper.java
  64. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/ClueUploadfileMapper.java
  65. 4 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/ContactsMapper.java
  66. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/CustomItemContactsMapper.java
  67. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/CustomMapper.java
  68. 6 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/OrderMapper.java
  69. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/OrderProductDetailMapper.java
  70. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/SeqMapper.java
  71. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/StageMapper.java
  72. 4 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/TaskMapper.java
  73. 23 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/UploadFileMapper.java
  74. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/ActionLogService.java
  75. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/BusinessItemCustomService.java
  76. 22 3
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/BusinessOpportunityService.java
  77. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/BusinessProductService.java
  78. 14 2
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/ClueService.java
  79. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/ClueUploadfileService.java
  80. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/CustomItemContactsService.java
  81. 33 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/CustomService.java
  82. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/OrderProductDetailService.java
  83. 2 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/OrderService.java
  84. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/SeqService.java
  85. 22 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/StageService.java
  86. 2 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/TaskService.java
  87. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/UploadFileService.java
  88. 20 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ActionLogServiceImpl.java
  89. 20 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/BusinessItemCustomServiceImpl.java
  90. 304 11
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/BusinessOpportunityServiceImpl.java
  91. 20 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/BusinessProductServiceImpl.java
  92. 257 49
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ClueServiceImpl.java
  93. 20 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ClueUploadfileServiceImpl.java
  94. 2 2
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ContactsServiceImpl.java
  95. 20 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/CustomItemContactsServiceImpl.java
  96. 378 3
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/CustomServiceImpl.java
  97. 20 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/OrderProductDetailServiceImpl.java
  98. 123 2
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/OrderServiceImpl.java
  99. 58 4
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ProductServiceImpl.java
  100. 0 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/SeqServiceImpl.java

+ 1 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/components/TaskModal/index.vue

@@ -167,7 +167,7 @@ watch(() => props.editForm, (val) => {
   changeTaskType(form.value.taskType)
   contactValueData.value = [{ label: '联系人1', value: 1 }, { label: '联系人2', value: 2 }];
   executorValueData.value = [{ label: '执行人1', value: 1 }, { label: '执行人2', value: 2 }];
-
+  
 })
 const rules = ref({
   taskName: [

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

@@ -0,0 +1,8 @@
+export const MOD = '/product'
+export const prefix = '/product'
+export const GETSYSFILED = '/sys-dict/getListByCode'
+export const GETPERSONNEL = '/user/getSimpleActiveUserList'
+export const GETTEMPLATE = `/sys-form/getListByCode${MOD}`
+export const GETTABLELIST = `${prefix}/list`
+export const ADDPRODUCT = `${prefix}/addOrUpdate`
+export const ALLDETELE = `${prefix}/delete`

+ 76 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/attachment.vue

@@ -0,0 +1,76 @@
+<template>
+    <div class="attachment pl-4 pr-4 pt-3 pb-3 h-full flex flex-col">
+        <div class="flex justify-between">
+            <div class="title">附件</div>
+            <div>
+                <el-button type="primary">上传</el-button>
+            </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 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>
+                    </template>
+                </el-table-column>
+            </el-table>
+        </div>
+    </div>
+</template>
+<script lang="ts" setup>
+import { ref, reactive, onMounted, onUnmounted, defineExpose, inject } from 'vue'
+
+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',
+}])
+// 生命周期钩子
+onMounted(() => {
+});
+</script>
+<style scoped lang="scss">
+.attachment {
+    .title {
+        font-size: 18px;
+        color: #000
+    }
+}
+</style>

Plik diff jest za duży
+ 73 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/information.vue


+ 58 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/operationRecord.vue

@@ -0,0 +1,58 @@
+<template>
+    <div class="operationRecord pl-4 pr-4 pt-3 pb-3 h-full flex flex-col">
+        <div class="flex justify-between">
+            <div class="title">操作记录</div>
+        </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>
+        </div>
+    </div>
+</template>
+<script lang="ts" setup>
+import { ref, reactive, onMounted, onUnmounted, defineExpose, inject } from 'vue'
+
+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',
+},])
+// 生命周期钩子
+onMounted(() => {
+});
+</script>
+<style scoped lang="scss">
+.operationRecord {
+    .title {
+        font-size: 18px;
+        color: #000
+    }
+}
+</style>

+ 93 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/products.vue

@@ -0,0 +1,93 @@
+<template>
+    <div class="relatedTasks pl-4 pr-4 pt-3 pb-3 h-full flex flex-col">
+        <div class="flex justify-between">
+            <div class="title">相关产品</div>
+            <div>
+                <el-button type="primary">编辑产品</el-button>
+            </div>
+        </div>
+        <div class="flex-1 overflow-auto pt-3">
+            <el-table :data="relatedTaskstable" border style="width: 100%;height: 300px;">
+                <el-table-column label="序号" width="80">
+                    <template #default="scope">
+                        {{ scope.$index + 1 }}
+                    </template>
+                </el-table-column>
+                <el-table-column prop="taskName" label="产品名称">
+                    <template #default="scope">
+                        <el-button link type="primary" size="large">{{
+                            scope.row.taskName
+                        }}</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="endTime" label="合计" width="130" />
+            </el-table>
+        </div>
+    </div>
+</template>
+<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',
+}])
+// 生命周期钩子
+onMounted(() => {
+});
+</script>
+<style scoped lang="scss">
+.relatedTasks {
+    .title {
+        font-size: 18px;
+        color: #000
+    }
+}
+</style>

+ 81 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/relatedBusiness.vue

@@ -0,0 +1,81 @@
+<template>
+    <div class="relatedTasks pl-4 pr-4 pt-3 pb-3 h-full flex flex-col">
+        <div class="flex justify-between">
+            <div class="title">相关商机</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="任务名称">
+                    <template #default="scope">
+                        <el-button link type="primary" size="large">{{
+                            scope.row.taskName
+                        }}</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>
+        </div>
+    </div>
+</template>
+<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',
+}])
+// 生命周期钩子
+onMounted(() => {
+});
+</script>
+<style scoped lang="scss">
+.relatedTasks {
+    .title {
+        font-size: 18px;
+        color: #000
+    }
+}
+</style>

+ 92 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/component/relatedProducts.vue

@@ -0,0 +1,92 @@
+<template>
+    <div>
+        <el-table ref="productTableRef" :data="productTable" border :row-class-name="tableRowClassName"
+            @row-click="tableRowItem" style="width: 100%;height: 200px">
+            <el-table-column label="序号" width="80">
+                <template #default="scope">
+                    <span>{{ scope.$index + 1 }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column prop="productName" label="产品名称" width="180">
+                <template #default="scope">
+                    <el-select v-model="productTable[scope.$index].productName" placeholder="请选择"
+                        v-if="productTableIndex == scope.$index" clearable @clear="clearTableItem(scope.$index)"
+                        @change="selectChange(scope.$index, productTable[scope.$index].productName)">
+                        <el-option v-for="item in productArrar" :key="item.id" :label="item.productName" :value="item.id" />
+                    </el-select>
+                    <span v-else>{{ productTable[scope.$index].productName }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column prop="productType" label="产品类型" width="180"></el-table-column>
+            <el-table-column prop="unit" label="单位" width="80"></el-table-column>
+            <el-table-column prop="price" label="标准价格" width="120"></el-table-column>
+            <el-table-column prop="stock" label="库存" width="80"></el-table-column>
+            <el-table-column prop="sellingPrice" label="售价" width="180">
+                <template #default="scope">
+                    <el-input-number v-model="productTable[scope.$index].sellingPrice" class="mx-4" :min="0" :max="100000000" controls-position="right" v-if="productTableIndex == scope.$index" />
+                    <span v-else>{{ productTable[scope.$index].sellingPrice }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column prop="quantity" label="数量" width="180">
+                <template #default="scope">
+                    <el-input-number v-model="productTable[scope.$index].quantity" class="mx-4" :min="0" :max="100000000" controls-position="right" v-if="productTableIndex == scope.$index" />
+                    <span v-else>{{ productTable[scope.$index].quantity }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column prop="discount" label="折扣(%)" width="180">
+                <template #default="scope">
+                    <el-input-number v-model="productTable[scope.$index].discount" class="mx-4" :min="0" :max="100" controls-position="right" v-if="productTableIndex == scope.$index" />
+                    <span v-else>{{ productTable[scope.$index].discount }}</span>
+                </template>
+            </el-table-column>
+            <el-table-column prop="total" label="合计" width="180"></el-table-column>
+            <el-table-column label="操作" fixed="right" width="120">
+                <template #default="scope">
+                    <el-button link type="primary" size="large" @click.stop="addTableItem(scope.$index)">添加</el-button>
+                    <el-button link type="danger" size="large" v-if="productTable.length > 1"
+                        @click.stop="deteleTableItem(scope.$index)">删除</el-button>
+                </template>
+            </el-table-column>
+        </el-table>
+    </div>
+</template>
+  
+<script lang="ts" setup>
+import { ref, reactive, onMounted, inject } from "vue";
+
+const productTable: any = ref([{}])
+const productTableIndex = ref(0) // 可以编辑索引
+const productArrar = ref([
+    { id: 1, productName: '产品1', productType: '类别1', unit: '台', price: '1122', stock: '100', sellingPrice: 0, quantity: 0, discount: 0, total: '' },
+    { id: 2, productName: '产品2', productType: '类别2', unit: '台', price: '2211', stock: '300', sellingPrice: 0, quantity: 0, discount: 0, total: '' },
+])
+
+function selectChange(index: number, val: number | string) {
+    let newObj = productArrar.value.find((item: any) => item.id == val)
+    console.log(newObj)
+    productTable.value.splice(index, 1, newObj)
+}
+
+function tableRowItem(row: any) {
+    productTableIndex.value = row.index
+}
+
+function tableRowClassName({ row, rowIndex, }: { row: any, rowIndex: number }) {
+    row.index = rowIndex
+    return ''
+}
+
+function addTableItem(index: number) {
+    productTable.value.splice(index + 1, 0, {})
+}
+
+function clearTableItem(index: number) {
+    productTable.value.splice(index, 0, {})
+}
+
+function deteleTableItem(index: number) {
+    productTable.value.splice(index, 1)
+}
+</script>
+  
+<style lang="scss" scoped></style>

+ 152 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/detail/index.vue

@@ -0,0 +1,152 @@
+<template>
+  <div class="h-full flex p-3 flex-col businessDetail">
+    <div class="w-full bg-white p-2 mb-2 shadow-md rounded-md flex items-center">
+      <div class="icon mr-4">
+        <el-link :underline="false" @click="backPath()">
+          <el-icon class="el-icon--right"><icon-view /></el-icon> 返回产品列表
+        </el-link>
+      </div>
+      <div class="mr-8">
+        <el-select v-model="value" placeholder="请选择" style="width: 150px">
+          <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
+        </el-select>
+      </div>
+    </div>
+    <!-- 内容 -->
+    <div class="flex-1 flex flex-col overflow-y-auto overflow-x-hidden scroll-bar">
+      <div class="w-full h-auto flex justify-between">
+        <div class="bg-white shadow-md rounded-md" style="width: 46%;">
+          <Information />
+        </div>
+        <div class="bg-white ml-2 shadow-md rounded-md flex-1">
+          <Attachment />
+        </div>
+      </div>
+
+      <div class="w-full h-auto flex justify-between mt-2">
+        <div class="bg-white shadow-md rounded-md" style="width: 65%;">
+          <RelatedBusiness />
+        </div>
+        <div class="bg-white ml-2 shadow-md rounded-md flex-1">
+          <OperationRecord />
+        </div>
+      </div>
+
+      <div class="w-full h-auto flex justify-between mt-2">
+        <div class="bg-white shadow-md rounded-md w-full">
+          <Products />
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+  
+<script lang="ts" setup>
+import { ref, reactive, onMounted, inject } from "vue";
+import type { FormInstance, FormRules } from 'element-plus'
+import { Edit, ArrowLeft as IconView } from '@element-plus/icons-vue'
+import { backPath } from '../../../utils/tools'
+
+import Information from '../component/information.vue'
+import Attachment from '../component/attachment.vue'
+import RelatedBusiness from '../component/relatedBusiness.vue';
+import OperationRecord from '../component/operationRecord.vue';
+import Products from '../component/products.vue';
+
+const value = ref('')
+const stageStatusVal = ref('')
+const options = [
+  {
+    value: 'Option1',
+    label: 'Option1',
+  },
+  {
+    value: 'Option2',
+    label: 'Option2',
+  },
+  {
+    value: 'Option3',
+    label: 'Option3',
+  },
+  {
+    value: 'Option4',
+    label: 'Option4',
+  },
+  {
+    value: 'Option5',
+    label: 'Option5',
+  },
+]
+
+
+function handleScroll(event: any) { // 滚表横向滚动
+  if (event.deltaY) {
+    event.preventDefault();
+    const element = event.currentTarget;
+    element.scrollLeft += event.deltaY;
+  }
+}
+</script>
+  
+<style lang="scss" scoped>
+.businessDetail {
+  .icon {
+    .el-link {
+      color: #0052CC;
+    }
+  }
+
+  .text {
+    .el-link {
+      color: #fff;
+      font-size: 14px;
+    }
+  }
+
+  .backDarkBlue {
+    background-color: #0052CC;
+    color: #fff;
+  }
+
+  .backGray {
+    background-color: #F4F5F7;
+    color: #000;
+  }
+
+  .startStep {
+    clip-path: polygon(0% 0%,
+        90% 0%,
+        100% 50%,
+        90% 100%,
+        0% 100%);
+  }
+
+  .nextStep {
+    clip-path: polygon(0% 0%,
+        90% 0%,
+        100% 50%,
+        90% 100%,
+        0% 100%,
+        10% 50%);
+  }
+
+  .endStep {
+
+    clip-path: polygon(0% 0%,
+        100% 0%,
+        100% 100%,
+        0% 100%,
+        10% 50%);
+  }
+
+  .itemPing {
+    padding-top: 4px;
+    padding-bottom: 4px;
+  }
+
+  .selectClas >>> .el-select__wrapper {
+    background-color: none !important;
+    box-shadow: none !important;
+  }
+}
+</style>

+ 264 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/product/index.vue

@@ -1,11 +1,273 @@
 <template>
-  <div>
-    product
+  <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="filterProductForm" label-width="70px" style="max-width: 600px">
+            <el-form-item label="产品编号">
+              <el-input v-model="filterProductForm.productCode" clearable placeholder="请输入"></el-input>
+            </el-form-item>
+            <el-form-item label="产品名称">
+              <el-input v-model="filterProductForm.productName" clearable placeholder="请输入"></el-input>
+            </el-form-item>
+            <el-form-item label="产品类别">
+              <el-select v-model="filterProductForm.type" placeholder="请选择" clearable>
+                <el-option v-for="item in fixedData.ProductType" :key="item.id" :label="item.name" :value="item.id" />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="负责人">
+              <el-select v-model="filterProductForm.userId" placeholder="请选择">
+                <el-option v-for="item in fixedData.Personnel" :key="item.id" :label="item.name" :value="item.id" />
+              </el-select>
+            </el-form-item>
+            <el-form-item label="创建时间">
+              <el-date-picker v-model="filterProductForm.startTime" 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="filterProductForm.endTime" 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="resetFilter()">重置</El-Button>
+          <El-button type="primary" class="w-full" @click="getProductTableList()">搜索</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" @click="editProduct(true)">新建产品</el-button>
+          <el-button type="primary">批量删除</el-button>
+          <el-button type="primary">回收站</el-button>
+          <el-button type="primary">导入</el-button>
+          <el-button type="primary">导出</el-button>
+        </div>
+        <div class="flex-1 w-full overflow-hidden">
+          <el-table ref="productTableRef" :data="productTableList" border v-loading="allLoading.productTableLading"
+            style="width: 100%;height: 100%;">
+            <el-table-column type="selection" width="55" />
+            <el-table-column prop="productCode" label="产品编号" width="180"></el-table-column>
+            <el-table-column prop="productName" label="产品名称" width="180">
+              <template #default="scope">
+                <el-button link type="primary" size="large" @click="toProductDetail(scope.row)">{{
+                  scope.row.productName
+                }}</el-button>
+              </template>
+            </el-table-column>
+            <el-table-column prop="type" label="产品类别" width="180"></el-table-column>
+            <el-table-column prop="unit" label="单位" width="180"></el-table-column>
+            <el-table-column prop="price" label="标准价格" width="180"></el-table-column>
+            <el-table-column prop="inventory" label="库存" width="180"></el-table-column>
+            <el-table-column prop="status" label="状态" width="180"></el-table-column>
+            <el-table-column prop="inchargerId" label="负责人" width="190"></el-table-column>
+            <el-table-column prop="creatorId" label="创建人" width="180"></el-table-column>
+            <el-table-column prop="createTime" label="创建时间" width="180"></el-table-column>
+            <el-table-column label="操作" fixed="right" width="200">
+              <template #default="scope">
+                <el-button link type="primary" size="large">编辑</el-button>
+                <el-button link type="danger" size="large" @click.stop="deteleRow([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" :page-size="filterProductForm.pageSize"
+            @size-change="handleSizeChange" @current-change="handleCurrentChange" :total="productTableTotal" :hide-on-single-page="true" />
+        </div>
+      </div>
+    </div>
+
+    <!-- 弹窗 -->
+    <el-dialog v-model="dialogVisible.editProductVisible" 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">{{ allText.editClueText }}</h4>
+          <div>
+            <el-button type="primary" @click="saveProductRow(true)" v-loading="allLoading.saveLoading">保存并新建</el-button>
+            <el-button type="primary" @click="saveProductRow(false)" v-loading="allLoading.saveLoading">保存</el-button>
+            <el-button @click="dialogVisible.editProductVisible = false">取消</el-button>
+          </div>
+        </div>
+      </template>
+      <div class="h-[60vh] overflow-y-auto scroll-bar pt-3" v-loading="allLoading.generateFormLading">
+        <div class="ml-4 mr-4">
+          <GenerateForm ref="generateForm" :data="productTemplate" :value="genereditForm" :key="generateFormKey" />
+        </div>
+      </div>
+    </el-dialog>
+
   </div>
 </template>
 
 <script lang="ts" setup>
+import { ref, reactive, onMounted, inject } from "vue";
+import { GETSYSFILED, MOD, GETPERSONNEL, GETTEMPLATE, GETTABLELIST, ADDPRODUCT, ALLDETELE } from './api'
+import { getAllListByCode, getFromValue, resetFromValue, getFirstDayOfMonth, getLastDayOfMonth, formatDate, createTaskFromType, confirmAction } from '@/utils/tools'
+import { FormInstance, FormRules, ElMessageBox, ElTable } from 'element-plus'
+import { post, get } from "@/utils/request";
+import { useRouter, useRoute } from "vue-router";
+import { GenerateForm } from '@zmjs/form-design';
+
+const router = useRouter()
+const globalPopup = inject<GlobalPopup>('globalPopup')
+const filterProductForm = reactive<filterProductFormType>({ // 筛选条件form
+  userId: '',
+  productName: '',
+  productCode: '',
+  startTime: getFirstDayOfMonth(new Date()),
+  endTime: formatDate(new Date()),
+  pageIndex: 1,
+  pageSize: 10,
+  id: '',
+  type: '',
+})
+const allLoading = reactive({
+  productTableLading: false,
+  generateFormLading: false,
+  saveLoading: false,
+})
+const dialogVisible = reactive({
+  editProductVisible: false,
+  taskModalVisible: false,
+  clueDialogVisible: false,
+  deteleClueDialogVisible: false
+})
+const allText = reactive({
+  editClueText: '新建产品',
+})
+const fixedData = reactive({
+  ProductType: [] as fixedDataInterface[],
+  Personnel: [] as personnelInterface[]
+})
+const productTableList = ref([]) // 产品table数据
+const productTableTotal = ref(0) // 产品 table 数据总数
+const productTableRef = ref<InstanceType<typeof ElTable>>() // 产品table dom
+const generateForm: any = ref(null) // 模板
+const productTemplate = ref({
+  list: [],
+  config: {}
+}) // 产品模板
+const genereditForm = ref({}) // 编辑表单
+const generateFormKey = ref(1)
+
+// 方法定义
+function deteleRow(items: any[]) {
+  let ids = items.map(item => item.id).join(',')
+  let str = items.map(item => item.productName).join(',')
+  confirmAction(`确定${items.length > 1 ? '批量删除' : '删除'}【${str}】线索吗?`).then(() => {
+    post(ALLDETELE, { ids: ids }).then(res => {
+      if (res.code != 'ok') {
+        globalPopup?.showError(res.msg)
+        return
+      }
+      globalPopup?.showSuccess('删除成功')
+      getProductTableList()
+    })
+  })
+}
+
+async function saveProductRow(flag: boolean) {
+  const data = await generateForm.value.getData()
+  let newData = { ...genereditForm.value, ...data }
+  allLoading.saveLoading = true
+  post(ADDPRODUCT, { ...newData }).then((res) => {
+    console.log(res)
+    if(res.code != 'ok') {
+      globalPopup?.showError(res.msg)
+      return
+    }
+    globalPopup?.showSuccess('保存成功')
+    if (!flag) {
+      genereditForm.value = {}
+      generateForm.value && generateForm.value.reset()
+      generateFormKey.value++
+    }
+    dialogVisible.editProductVisible = flag
+  }).catch(() => {
+    dialogVisible.editProductVisible = flag
+  }).finally(() => {
+    allLoading.saveLoading = false
+  })
+}
+
+function editProduct(_flag: boolean) {
+  dialogVisible.editProductVisible = true
+  allLoading.generateFormLading = true
+  setTimeout(() => {
+    generateForm.value && generateForm.value.reset()
+    generateFormKey.value++
+    allLoading.generateFormLading = false
+  }, 1000)
+}
+
+function getProductTableList() {
+  allLoading.productTableLading = true
+  let valueForm = getFromValue(filterProductForm)
+  post(GETTABLELIST, { ...valueForm }).then((res) => {
+    if(res.code == 'ok') {
+      const { record, total } = res.data
+      productTableList.value = record
+      productTableTotal.value = total
+    }
+  }).finally(() => {
+    allLoading.productTableLading = false
+  })
+}
+
+function handleSizeChange(val: number) {
+  filterProductForm.pageIndex = 1
+  filterProductForm.pageSize = val
+  getProductTableList()
+}
+
+function handleCurrentChange(val: number) {
+  filterProductForm.pageIndex = val
+  getProductTableList()
+}
+
+function resetFilter() {
+  let newResetForm = resetFromValue(filterProductForm, { startTime: getFirstDayOfMonth(new Date()), endTime: formatDate(new Date()), pageIndex: 1, pageFrom: 10 })
+  Object.assign(filterProductForm, newResetForm)
+  getProductTableList()
+}
+
+function toProductDetail(row: any) {
+  router.push({ 
+    path: `${MOD}/detail`, 
+    query: { id: row.id } 
+  })
+}
+
+async function getSystemField() {
+  const systemField = getAllListByCode(['产品类型'])
+  for (let i in systemField) {
+    const { data } = await get(`${GETSYSFILED}?code=${systemField[i]}`)
+    for (let key of Object.keys(fixedData)) {
+      if (systemField[i] == key) {
+        Object.assign(fixedData, { [key]: data })
+      }
+    }
+  }
+
+  const { data } = await post(GETPERSONNEL, {})
+  fixedData.Personnel = data.map((item: any) => {
+    const { id, name, phone, jobNumber } = item
+    return {
+      id, name, phone, jobNumber
+    }
+  })
+
+  const res = await get(GETTEMPLATE)
+  productTemplate.value = JSON.parse(res.data[0].config)
+}
 
+onMounted(() => {
+  getSystemField()
+  getProductTableList()
+})
 </script>
 
 <style lang="scss" scoped></style>

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

@@ -0,0 +1,11 @@
+interface filterProductFormType {
+    userId: string | number,
+    productName: string,
+    productCode: string,
+    pageIndex: number,
+    pageSize: number,
+    type: string | number,
+    id: string | number,
+    startTime: string,
+    endTime: string
+}

+ 2 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/system/customForm/index.vue

@@ -177,7 +177,8 @@ function handleClose(done: any) {
 function setData() {
   // let data = JSON.parse(localStorage.getItem('threadDataJson') || '')
   // let data = JSON.parse(localStorage.getItem('business') || '')
-  let data = JSON.parse(localStorage.getItem('tasks') || '')
+  // let data = JSON.parse(localStorage.getItem('tasks') || '')
+  let data = JSON.parse(localStorage.getItem('product') || '')
   data.list.forEach((element: any) => {
     element.allDisable = true
   });

+ 9 - 1
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/constant.ts

@@ -2,8 +2,16 @@ export const MOD = '/thread'
 export const prefix = '/clue'
 export const GETSYSFILED = '/sys-dict/getListByCode'
 export const GETPERSONNEL = '/user/getSimpleActiveUserList'
+export const GETTEMPLATE = `/sys-form/getListByCode${MOD}`
 export const GETTABLE = `${prefix}/listClue`
 export const GETDETAIL = `${prefix}/getDetail`
 export const UNDATECLAIM = `${prefix}/claim`
 export const UNDATEFORM = `${prefix}/insertAndUpdate`
-export const DELTEROW = `${prefix}/delete`
+export const DELTEROW = `${prefix}/delete`
+export const DETELEFILE = `${prefix}/deleteFile`
+export const DOWNFILE = `${prefix}/downFile`
+export const REFIENAME = `${prefix}/reFileName`
+export const UPLOADFILE = `${prefix}/uploadFile`
+export const DEYELWCLUE = `${prefix}/listDeleterClue`
+export const DETERDETELE = `${prefix}/deleterDelete`
+export const ROLLBACK = `${prefix}/rollback`

+ 118 - 45
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/components/attachment.vue

@@ -3,67 +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="正在上传">
+                    <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: 100%;">
-                <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="name" label="附件名称" width="200" />
+                <el-table-column prop="size" label="附件大小" width="120" />
+                <el-table-column prop="userName" label="上传人" width="120" />
+                <el-table-column prop="createTime" 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="showVisible(scope.row)">重命名</el-button>
+                        <el-button link type="danger" size="large" @click="deteleFile(scope.row)">删除</el-button>
                     </template>
                 </el-table-column>
             </el-table>
         </div>
+
+        <!-- 弹窗 -->
+        <el-dialog v-model="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()">保存</el-button>
+                        <el-button @click="renameDialogVisible = false">取消</el-button>
+                    </div>
+                </div>
+            </template>
+            <div class="pt-3">
+                <el-input v-model.trim="renameVal" style="width: 100%" class="pb-3" clearable />
+            </div>
+        </el-dialog>
     </div>
 </template>
 <script lang="ts" setup>
-import { ref, reactive, onMounted, onUnmounted, defineExpose, inject } from 'vue'
+import { ElMessageBox, UploadRequestOptions } from 'element-plus';
+import { ref, watch, onMounted, inject, defineEmits, watchEffect } from 'vue'
+import { uploadFile, post } from '@/utils/request'
+import { formatDate, downloadFile, confirmAction } from '@/utils/tools'
+import { DETELEFILE, DOWNFILE, REFIENAME, UPLOADFILE } from '../../constant';
+
+const globalPopup = inject<GlobalPopup>('globalPopup')
+const emits = defineEmits(['refreshData']);
+const attachmenttable = ref([])
+const information: any = ref({})
+const renameDialogVisible = ref(false)
+const renameVal = ref('')
+const props = defineProps<{
+    data: any,
+    information: any
+}>()
+
+// 下载文件
+function fileDownload(item: any) {
+    const id = item.id
+    post(DOWNFILE, { id }).then((res) => {
+        downloadFile(res, item.name)
+    }).catch((err) => {
+        downloadFile(err, item.name)
+    })
+}
+
+// 删除文件
+function deteleFile(item: any) {
+    const id = item.id
+    confirmAction(`确定删除【${item.name}】文件吗?`).then(() => {
+        post(DETELEFILE, { id }).then((_res) => {
+            globalPopup?.showSuccess('删除成功')
+            emits('refreshData')
+        })
+    })
+}
+
+// 保存重命名
+function saveEditClue() {
+    if (!renameVal.value) {
+        globalPopup?.showWarning('请输入文件名称')
+        return
+    }
+    const clueId = information.value.id
+    post(REFIENAME, { name: renameVal.value, id: clueId }).then((res) => {
+        if (res.code == 'ok') {
+            renameDialogVisible.value = false
+            globalPopup?.showSuccess(res.msg || '')
+            emits('refreshData')
+        }
+    }).catch((_err) => { })
+}
+
+// 显示弹窗
+function showVisible(item: any) {
+    renameVal.value = JSON.parse(JSON.stringify(item.name))
+    renameDialogVisible.value = true
+}
+
+// 上传附件
+async function httpUploadFile(param: UploadRequestOptions) {
+    const clueId = information.value.id
+    const formData = new FormData();
+    formData.append('file', param.file)
+    formData.append('id', clueId)
+    const res = await uploadFile(UPLOADFILE, formData)
+    if (res.code == 'ok') {
+        globalPopup?.showSuccess(res.msg || '')
+        emits('refreshData');
+        return
+    }
+    globalPopup?.showError(res.msg || '')
+    return res
+}
+
+// 接收参数赋值
+function receiveAssignment(item: any) {
+    item.data.forEach((item: any) => {
+        item.createTime = formatDate(new Date(item.createTime))
+    });
+    attachmenttable.value = item.data
+    information.value = item.information
+}
+
+watchEffect(() => {
+    receiveAssignment(props)
+});
 
-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',
-}])
 // 生命周期钩子
 onMounted(() => {
+    receiveAssignment(props)
 });
 </script>
 <style scoped lang="scss">

Plik diff jest za duży
+ 208 - 17
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/components/information.vue


+ 18 - 35
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/components/operationRecord.vue

@@ -5,48 +5,31 @@
         </div>
         <div class="flex-1 overflow-auto pt-5">
             <el-table :data="operationRecordtable" border style="width: 100%;height: 100%;">
-                <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="creatTime" label="操作时间" width="140" />
+                <el-table-column prop="userName" label="操作人" width="120" />
+                <el-table-column prop="name" label="操作内容" />
             </el-table>
         </div>
     </div>
 </template>
 <script lang="ts" setup>
-import { ref, reactive, onMounted, onUnmounted, defineExpose, inject } from 'vue'
+import { formatDate } from '@/utils/tools';
+import { ref, onMounted, watchEffect } from 'vue'
 
-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',
-},])
-// 生命周期钩子
-onMounted(() => {
+const props = defineProps<{
+    data: any
+}>()
+
+const operationRecordtable = ref([])
+
+watchEffect(() => {
+    props.data.forEach((item: any) => {
+        item.creatTime = formatDate(new Date(item.creatTime))
+    })
+    operationRecordtable.value = props.data
 });
+// 生命周期钩子
+onMounted(() => {});
 </script>
 <style scoped lang="scss">
 .operationRecord {

+ 40 - 5
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/detail/index.vue

@@ -2,35 +2,70 @@
   <div class="h-full threadDetail">
     <div class="layout p-3">
       <div class="bg-white w-1/2 shadow-md rounded-md">
-        <Information></Information>
+        <Information :data="information" @refreshData="refreshData"></Information>
       </div>
       <div class="bg-white w-1/2 ml-3 shadow-md rounded-md">
-        <Attachment></Attachment>
+        <Attachment :data="attachment" :information="information" @refreshData="refreshData"></Attachment>
       </div>
     </div>
     <div class="layout pl-3 pr-3 pb-3">
       <div class="bg-white w-2/3 shadow-md rounded-md">
-        <RelatedTasks></RelatedTasks>
+        <RelatedTasks :data="relatedTasks" :information="information" @refreshData="refreshData"></RelatedTasks>
       </div>
       <div class="bg-white w-1/3 ml-3 shadow-md rounded-md">
-        <OperationRecord></OperationRecord>
+        <OperationRecord :data="operationRecord" :information="information" @refreshData="refreshData"></OperationRecord>
       </div>
     </div>
   </div>
 </template>
   
 <script lang="ts" setup>
-
 import Information from './components/information.vue'
 import Attachment from './components/attachment.vue'
 import RelatedTasks from './components/relatedTasks.vue';
 import OperationRecord from './components/operationRecord.vue';
+import { ref, reactive, onMounted, inject } from "vue";
+import { post, get } from "@/utils/request";
+import { useRouter, useRoute } from "vue-router";
+import { GETDETAIL } from "../constant"
+
+const route = useRoute()
+
+const globalPopup = inject<GlobalPopup>('globalPopup')
+const addressParameters: any = ref(0) // 地址上的参数
+const information = ref({}) // 基本信息
+const attachment = ref([]) // 附件
+const relatedTasks = ref([]) // 相关任务
+const operationRecord = ref([]) // 操作记录
+
+function getDetail() {
+  const id = addressParameters.value
+  post(GETDETAIL, { id }).then((res) => {
+    const { clueLogList, files, taskList } = res.data
+    information.value = res.data
+    attachment.value = files || []
+    relatedTasks.value = taskList || []
+    operationRecord.value = clueLogList || []
+  })
+}
+
+function refreshData() {
+  getDetail()
+}
+
+onMounted(() => {
+  const { id } = route.query
+  addressParameters.value = id
+  getDetail()
+
+})
 </script>
   
 <style lang="scss" scoped>
 .threadDetail {
   display: flex;
   flex-direction: column;
+
   .layout {
     width: 100%;
     height: 50%;

+ 166 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/deteleTables.vue

@@ -0,0 +1,166 @@
+<template>
+    <el-dialog v-model="deteleClueDialogVisible" width="1000" :before-close="beForeCancel" :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="batchRestore()" v-loading="allLoading.batchRecoveryLoading">批量恢复</el-button>
+                    <el-button type="primary" @click="batchDeletes()"
+                        v-loading="allLoading.batchDeteleLoading">批量删除</el-button>
+                    <el-button @click="cancel()">取消</el-button>
+                </div>
+            </div>
+        </template>
+        <div class="h-[60vh] flex flex-col">
+            <div class="flex-1 w-full overflow-hidden">
+                <el-table ref="clueTableRef" :data="deteleClueTable" border v-loading="allLoading.tableLoading"
+                    style="width: 100%;height: 100%;">
+                    <el-table-column type="selection" width="55" />
+                    <el-table-column prop="clueName" label="线索名称" width="180"></el-table-column>
+                    <el-table-column prop="clueSourceValue" label="线索来源" width="180"></el-table-column>
+                    <el-table-column prop="phone" label="电话号码" width="180"></el-table-column>
+                    <el-table-column prop="email" label="邮箱" width="180"></el-table-column>
+                    <el-table-column prop="customerIndustryValue" label="客户行业" width="180"></el-table-column>
+                    <el-table-column prop="customerLevelValue" label="客户级别" width="180"></el-table-column>
+                    <el-table-column prop="inchargerName" label="负责人" width="190"></el-table-column>
+                    <el-table-column prop="createName" label="创建人" width="180"></el-table-column>
+                    <el-table-column prop="createTime" label="创建时间" width="180"></el-table-column>
+                    <el-table-column label="操作" fixed="right" width="120">
+                        <template #default="scope">
+                            <el-button link type="primary" size="large" @click="restoreItemRow([scope.row])">恢复</el-button>
+                            <el-button link type="danger" size="large" @click="deteItemRow([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" :page-size="tableForm.pageFrom"
+                    @size-change="handleSizeChange" @current-change="handleCurrentChange" :total="clueTotalTable"
+                    :hide-on-single-page="true" />
+            </div>
+        </div>
+    </el-dialog>
+</template>
+<script lang="ts" setup>
+import { post } from '@/utils/request';
+import { ref, reactive, onMounted, watchEffect, watch, inject } from 'vue'
+import { DETERDETELE, DEYELWCLUE, ROLLBACK } from './constant';
+import { ElTable } from 'element-plus';
+import { confirmAction } from '@/utils/tools';
+
+const emits = defineEmits(['showDeteleClue']);
+const globalPopup = inject<GlobalPopup>('globalPopup')
+const deteleClueTable = ref([])
+const deteleClueDialogVisible = ref(false)
+const clueTotalTable = ref(0)
+const allLoading = reactive({
+    batchRecoveryLoading: false,
+    batchDeteleLoading: false,
+    tableLoading: false
+})
+
+const tableForm = reactive({
+    pageIndex: 1,
+    pageFrom: 10
+})
+
+const clueTableRef = ref<InstanceType<typeof ElTable>>() // 线索table dom
+
+const props = defineProps<{
+    visibles: boolean
+}>()
+
+watch(() => props.visibles, (newVal) => {
+    deteleClueDialogVisible.value = newVal
+    if (newVal) {
+        getTableList()
+    }
+})
+
+function batchRestore() {
+    const data = clueTableRef.value && clueTableRef.value.getSelectionRows()
+    if (!data.length) {
+        globalPopup?.showWarning('请选择需要恢复的数据')
+        return
+    }
+    restoreItemRow(data)
+}
+
+function batchDeletes() {
+    const data = clueTableRef.value && clueTableRef.value.getSelectionRows()
+    if (!data.length) {
+        globalPopup?.showWarning('请选择需要删除的数据')
+        return
+    }
+    deteItemRow(data)
+}
+
+function deteItemRow(items: any[]) {
+    const ids = items.map((item: any) => item.id).join(',')
+    const str = items.map((item: any) => item.clueName).join(',')
+    confirmAction(`确定${items.length > 1 ? '批量删除这些' : '删除'}【${str}】线索吗?`, '', 'warning').then(() => {
+    post(DETERDETELE, { ids }).then(res => {
+      if (res.code != 'ok') {
+        globalPopup?.showError(res.msg)
+        return
+      }
+      globalPopup?.showSuccess('删除成功')
+      getTableList()
+    })
+  })
+}
+
+function restoreItemRow(items: any[]) {
+    const ids = items.map((item: any) => item.id).join(',')
+    const str = items.map((item: any) => item.clueName).join(',')
+    confirmAction(`确定${items.length > 1 ? '批量恢复这些' : '恢复'}【${str}】线索吗?`, '', 'warning').then(() => {
+    post(ROLLBACK, { ids }).then(res => {
+      if (res.code != 'ok') {
+        globalPopup?.showError(res.msg)
+        return
+      }
+      globalPopup?.showSuccess('恢复成功')
+      getTableList()
+    })
+  })
+}
+
+function getTableList() {
+    allLoading.tableLoading = true
+    post(DEYELWCLUE, { ...tableForm }).then((res) => {
+        if (res.code == 'ok') {
+            const { data, total } = res.data
+            deteleClueTable.value = data
+            clueTotalTable.value = total
+        }
+    }).finally(() => {
+        allLoading.tableLoading = false
+    })
+}
+
+function handleSizeChange(val: number) {
+    tableForm.pageIndex = 1
+    tableForm.pageFrom = val
+    getTableList()
+}
+
+function handleCurrentChange(val: number) {
+    tableForm.pageIndex = val
+    getTableList()
+}
+
+function cancel() {
+    emits('showDeteleClue', false)
+}
+
+function beForeCancel(done: () => void) {
+    emits('showDeteleClue', false)
+    done()
+}
+
+onMounted(() => {
+
+})
+
+</script>
+<style lang="scss" scoped></style>

+ 222 - 28
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/index.vue

@@ -8,7 +8,7 @@
               <el-input v-model="filterCriteriaForm.clueName" clearable placeholder="请输入"></el-input>
             </el-form-item>
             <el-form-item label="线索来源">
-              <el-select v-model="filterCriteriaForm.clueSourceId" placeholder="请选择">
+              <el-select v-model="filterCriteriaForm.clueSourceId" placeholder="请选择" clearable>
                 <el-option v-for="item in fixedData.ClueSources" :key="item.id" :label="item.name" :value="item.id" />
               </el-select>
             </el-form-item>
@@ -52,10 +52,10 @@
     <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">新建线索</el-button>
+          <el-button type="primary" @click="editClue(false)">新建线索</el-button>
           <el-button type="primary" @click="batchTransfer()">批量转移</el-button>
-          <el-button type="primary" @clicl="batchDelete()">批量删除</el-button>
-          <el-button type="primary">回收站</el-button>
+          <el-button type="primary" @click="batchDeletes()">批量删除</el-button>
+          <el-button type="primary" @click="showDeteleClue(true)">回收站</el-button>
           <el-button type="primary">导入</el-button>
           <el-button type="primary">导出</el-button>
         </div>
@@ -65,44 +65,94 @@
             <el-table-column type="selection" width="55" />
             <el-table-column prop="clueName" label="线索名称" width="180">
               <template #default="scope">
-                <el-button link type="primary" size="large" @click.prevent="toClueTableDetail(scope.row)">{{ scope.row.clueName
+                <el-button link type="primary" size="large" @click.prevent="toClueTableDetail(scope.row)">{{
+                  scope.row.clueName
                 }}</el-button>
               </template>
             </el-table-column>
-            <el-table-column prop="clueSourceId" label="线索来源" width="180"></el-table-column>
+            <el-table-column prop="clueSourceValue" label="线索来源" width="180"></el-table-column>
             <el-table-column prop="phone" label="电话号码" width="180"></el-table-column>
             <el-table-column prop="email" label="邮箱" width="180"></el-table-column>
-            <el-table-column prop="customerIndustryId" label="客户行业" width="180"></el-table-column>
-            <el-table-column prop="customerLevelId" label="客户级别" width="180"></el-table-column>
-            <el-table-column prop="inchargerId" label="负责人" width="190"></el-table-column>
+            <el-table-column prop="customerIndustryValue" label="客户行业" width="180"></el-table-column>
+            <el-table-column prop="customerLevelValue" label="客户级别" width="180"></el-table-column>
+            <el-table-column prop="inchargerName" label="负责人" width="190"></el-table-column>
             <el-table-column prop="createName" label="创建人" width="180"></el-table-column>
             <el-table-column prop="createTime" label="创建时间" width="180"></el-table-column>
             <el-table-column label="操作" fixed="right" width="200">
               <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" @click.prevent="deleteRow(scope.$index)">删除</el-button>
+                <el-button link type="primary" size="large" @click="editClue(scope.row)">编辑</el-button>
+                <el-button link type="primary" size="large"
+                  @click="dialogVisible.taskModalVisible = true">新建任务</el-button>
+                <el-button link type="danger" size="large" @click.prevent="deleteRow(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" :total="clueTotalTable" :hide-on-single-page="true" />
+          <el-pagination layout="total, prev, pager, next, sizes" :page-size="filterCriteriaForm.pageFrom"
+            @size-change="handleSizeChange" @current-change="handleCurrentChange" :total="clueTotalTable"
+            :hide-on-single-page="true" />
         </div>
       </div>
     </div>
 
     <!-- 弹窗 -->
-    
+    <el-dialog v-model="dialogVisible.editClueDialogVisible" 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">{{ allText.editClueText }}</h4>
+          <div>
+            <el-button type="primary" @click="saveEditClue(true)">保存并新建</el-button>
+            <el-button type="primary" @click="saveEditClue(false)">保存</el-button>
+            <el-button @click="dialogVisible.editClueDialogVisible = false">取消</el-button>
+          </div>
+        </div>
+      </template>
+      <div class="h-[60vh] overflow-y-auto scroll-bar pt-3" v-loading="allLoading.generateFormLading">
+        <div class="ml-4 mr-4">
+          <GenerateForm ref="generateForm" :data="clueTemplate" :value="editForm" :key="generateFormKey" />
+        </div>
+      </div>
+    </el-dialog>
+
+    <el-dialog v-model="dialogVisible.clueDialogVisible" 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.clueText }}</h4>
+          <div>
+            <el-button type="primary" v-loading="allLoading.clueLoading" @click="transferClues()">转移</el-button>
+            <el-button @click="dialogVisible.clueDialogVisible = 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="transferForm.transferValue" placeholder="请选择" class="flex1">
+            <el-option v-for="item in fixedData.Personnel" :key="item.id" :label="item.name" :value="item.id" />
+          </el-select>
+        </div>
+        <div class="pl-3 text-[#e94a4a]">转移后,将看不到此线索</div>
+      </div>
+    </el-dialog>
+
+    <DeteleTables :visibles="dialogVisible.deteleClueDialogVisible" @showDeteleClue="showDeteleClue" />
+
+    <TaskModal :visible="dialogVisible.taskModalVisible" :edit-form="createTaskFromType(3)" :save-loading="'1'"
+      @close="closeTaskModal" @submit="submitForm" />
   </div>
 </template>
 
 <script lang="ts" setup>
 import { ref, reactive, onMounted, inject } from "vue";
-import { GETSYSFILED, MOD, GETPERSONNEL, GETTABLE, GETDETAIL, UNDATECLAIM, UNDATEFORM, DELTEROW } from './constant'
-import { getAllListByCode, getFromValue, resetFromValue, getFirstDayOfMonth, getLastDayOfMonth, formatDate } from '@/utils/tools'
+import { GETSYSFILED, MOD, GETPERSONNEL, GETTABLE, GETTEMPLATE, GETDETAIL, UNDATECLAIM, UNDATEFORM, DELTEROW } from './constant'
+import { getAllListByCode, getFromValue, resetFromValue, getFirstDayOfMonth, getLastDayOfMonth, formatDate, createTaskFromType, confirmAction } from '@/utils/tools'
+import { FormInstance, FormRules, ElMessageBox, ElTable } from 'element-plus'
 import { post, get } from "@/utils/request";
 import { useRouter, useRoute } from "vue-router";
+import { GenerateForm } from '@zmjs/form-design';
+import TaskModal from '@/components/TaskModal/index.vue'
+import DeteleTables from "./deteleTables.vue";
 
 // 定义类型
 interface fixedDataInterface {
@@ -137,8 +187,21 @@ const filterCriteriaForm = reactive<filterCriteriaFormType>({ // 筛选条件for
   pageIndex: 1,
   pageFrom: 10
 })
+const generateFormKey = ref(1)
 const allLoading = reactive({
   clueTableLading: false,
+  generateFormLading: false,
+  clueLoading: false,
+})
+const dialogVisible = reactive({
+  editClueDialogVisible: false,
+  taskModalVisible: false,
+  clueDialogVisible: false,
+  deteleClueDialogVisible: false
+})
+const allText = reactive({
+  editClueText: '新建线索',
+  clueText: '转移线索'
 })
 const fixedData = reactive({
   ClueSources: [] as fixedDataInterface[],
@@ -146,10 +209,45 @@ const fixedData = reactive({
   CustomLevel: [] as fixedDataInterface[],
   Personnel: [] as personnelInterface[]
 })
-const clueTable = ref([{ clueName: '线索名称', clueSourceId: '线索来源', id: 123456789 }]) // 线索table数据
+const clueTable = ref([]) // 线索table数据
 const clueTotalTable = ref(0) // 线索 table 数据总数
+const clueTableRef = ref<InstanceType<typeof ElTable>>() // 线索table dom
+const generateForm: any = ref(null) // 模板
+const clueTemplate = ref({
+  list: [],
+  config: {}
+}) // 线索模板
+const editForm = ref({}) // 编辑表单
+
+// 批量变量
+const transferForm = reactive({
+  transferValue: '',
+  batchTransferIds: '',
+})
+
 
 // 定义方法
+function showDeteleClue(flag: boolean) {
+  dialogVisible.deteleClueDialogVisible = flag
+}
+
+function transferClues() {
+  const { transferValue, batchTransferIds } = transferForm
+  const ids = batchTransferIds
+  const inchargerId = transferValue
+  if (!inchargerId) {
+    globalPopup?.showWarning('请选择转移的人员')
+    return
+  }
+  post(UNDATECLAIM, { ids, inchargerId }).then((res) => {
+    if (res.code == 'ok') {
+      globalPopup?.showSuccess('批量转移成功')
+      dialogVisible.clueDialogVisible = false
+      getClueTable()
+    }
+  })
+}
+
 function searchTable() {
   getClueTable()
 }
@@ -160,23 +258,102 @@ function resetTable() {
   getClueTable()
 }
 
-function deleteRow(_row: any) {
-  console.log('点击了删除')
+function closeTaskModal() {
+  dialogVisible.taskModalVisible = false
+}
+
+function submitForm(submitData: any, isClose: boolean) {
+  console.log(submitData, isClose)
+}
+
+function editClue(item: any) {
+  dialogVisible.editClueDialogVisible = true
+  allLoading.generateFormLading = true
+  setTimeout(() => {
+    generateForm.value && generateForm.value.reset()
+    generateFormKey.value++
+    allLoading.generateFormLading = false
+  }, 1000);
+  if (!item) {
+    allText.editClueText = '新建线索'
+    editForm.value = {}
+    return
+  }
+  editForm.value = JSON.parse(JSON.stringify(item))
+  allText.editClueText = '编辑线索'
+}
+
+async function saveEditClue(flag: boolean) {
+  const data = await generateForm.value.getData()
+  let newData = { ...editForm.value, ...data }
+  delete newData.createTime
+  post(UNDATEFORM, { ...newData }).then((res) => {
+    if (res.code != 'ok') {
+      globalPopup?.showError(res.msg)
+      return
+    }
+    globalPopup?.showSuccess('保存成功')
+    if (!flag) {
+      editForm.value = {}
+      generateForm.value && generateForm.value.reset()
+      generateFormKey.value++
+    }
+    dialogVisible.editClueDialogVisible = flag
+    getClueTable()
+  }).catch((_err) => {
+    console.log(_err)
+  })
+}
+
+function deleteRow(row: any) {
+  confirmAction(`确定删除【${row.clueName}】线索吗?`).then(() => {
+    post(DELTEROW, { ids: row.id }).then(res => {
+      if (res.code != 'ok') {
+        globalPopup?.showError(res.msg)
+        return
+      }
+      globalPopup?.showSuccess('删除成功')
+      getClueTable()
+    })
+  })
 }
 
 function batchTransfer() {
-  console.log('点击了批量转移')
+  const data = clueTableRef.value && clueTableRef.value.getSelectionRows()
+  if (!data.length) {
+    globalPopup?.showWarning('请选择数据')
+    return
+  }
+  transferForm.batchTransferIds = data.map((item: any) => item.id).join(',')
+  dialogVisible.clueDialogVisible = true
 }
 
-function batchDelete() {
-  console.log('批量删除')
+function batchDeletes() {
+  const data = clueTableRef.value && clueTableRef.value.getSelectionRows()
+  if (!data.length) {
+    globalPopup?.showWarning('请选择数据')
+    return
+  }
+  const str = data.map((item: any) => item.clueName).join(',')
+  const ids = data.map((item: any) => item.id).join(',')
+
+  confirmAction(`确定批量删除这些【${str}】线索吗?`, '', 'warning').then(() => {
+    post(DELTEROW, { ids }).then(res => {
+      if (res.code != 'ok') {
+        globalPopup?.showError(res.msg)
+        return
+      }
+      globalPopup?.showSuccess('删除成功')
+      getClueTable()
+    })
+  })
 }
 
 function toClueTableDetail(row: any) {
   console.log('点击跳转详情')
-  router.push({ 
-    path: `${MOD}/detail`, 
-    query: { id: row.id } 
+  router.push({
+    path: `${MOD}/detail`,
+    query: { id: row.id }
   })
 }
 
@@ -184,15 +361,29 @@ function getClueTable() {
   allLoading.clueTableLading = true
   let valueForm = getFromValue(filterCriteriaForm)
   post(GETTABLE, { ...valueForm }).then((res: any) => {
-    const { total, data } = res
-    clueTable.value = data
-    clueTotalTable.value = total
+    let { data } = res
+    for (let i in data.data) {
+      data.data[i].createTime = formatDate(new Date(data.data[i].createTime))
+    }
+    clueTable.value = data.data
+    clueTotalTable.value = data.total
     allLoading.clueTableLading = false
   }).catch((_error) => {
     allLoading.clueTableLading = false
   })
 }
 
+function handleSizeChange(val: number) {
+  filterCriteriaForm.pageIndex = 1
+  filterCriteriaForm.pageFrom = val
+  getClueTable()
+}
+
+function handleCurrentChange(val: number) {
+  filterCriteriaForm.pageIndex = val
+  getClueTable()
+}
+
 async function getSystemField() {
   const systemField = getAllListByCode(['线索来源', '客户行业', '客户级别'])
   for (let i in systemField) {
@@ -211,6 +402,9 @@ async function getSystemField() {
       id, name, phone, jobNumber
     }
   })
+
+  const res = await get(GETTEMPLATE)
+  clueTemplate.value = JSON.parse(res.data[0].config)
 }
 
 onMounted(() => {

+ 2 - 2
fhKeeper/formulahousekeeper/customerBuler-crm/src/pages/thread/type.d.ts

@@ -8,6 +8,6 @@ interface filterCriteriaFormType { // 线索筛选条件类型
   inchargerId: string | number,
   startTime: string | number,
   endTime: string | number,
-  pageIndex: string | number,
-  pageFrom: string | number
+  pageIndex: number,
+  pageFrom: number
 }

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

@@ -24,4 +24,6 @@ type ListByCodeType = (
 type saveLoadingType = "1" | "2" | "3" | "4"; //1是没有保存, 2是正在保存, 3是保存成功, 4是保存失败
 
 type TASK_VALUE_TYPE = 0 | 1 | 2 | 3; //0是客户, 1是商机, 2是销售订单 ,3是线索
-type REPEAT_VALUE_TYPE = 0 | 1 | 2 | 3 | 4; //0是每天, 1是每周, 2是每月, 3是自定义周期, 4是自定义日期
+type REPEAT_VALUE_TYPE = 0 | 1 | 2 | 3 | 4; //0是每天, 1是每周, 2是每月, 3是自定义周期, 4是自定义日期
+
+type componentType = "success" | "info" | "warning" | "error"

+ 31 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/times.ts

@@ -0,0 +1,31 @@
+/**
+ * 获取当月第一天
+ * @param date 日期 new Date()
+ * @returns
+ */
+export function getFirstDayOfMonth(date: Date) {
+  const firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
+  return formatDate(firstDay);
+}
+
+/**
+ * 获取当月最后一天
+ * @param date 日期 new Date()
+ * @returns
+ */
+export function getLastDayOfMonth(date: Date) {
+  const nextMonth = new Date(date.getFullYear(), date.getMonth() + 1, 0);
+  return formatDate(nextMonth);
+}
+
+/**
+ * 将 Date 对象格式化为 "YYYY-MM-DD" 的形式
+ * @param date 日期 new Date()
+ * @returns
+ */
+export function formatDate(date: Date) {
+  const year = date.getFullYear();
+  const month = (1 + date.getMonth()).toString().padStart(2, "0");
+  const day = date.getDate().toString().padStart(2, "0");
+  return `${year}-${month}-${day}`;
+}

+ 55 - 0
fhKeeper/formulahousekeeper/customerBuler-crm/src/utils/tools.ts

@@ -1,3 +1,5 @@
+import { defalutModalForm } from '@/components/TaskModal/api'
+import { ElMessageBox } from 'element-plus';
 /**
  * 判断值是否为空
  * @param value 值
@@ -139,6 +141,59 @@ export function formatDate(date: Date) {
   return `${year}-${month}-${day}`;  
 }  
 
+/**
+ * 获取创建任务的 form
+ * @param taskType 任务类型
+ * @returns form
+ */
+export function createTaskFromType(taskType: TASK_VALUE_TYPE) {
+  return {
+    ...defalutModalForm,
+    taskType
+  }
+}
+
+/**
+ * 下载文件
+ * @param dataFile 接口返回的数据
+ * @param fileName 文件名称
+ */
+export function downloadFile(dataFile: any, fileName: string) {
+  const data = dataFile;
+  const blob = new Blob([data]);
+  const url = window.URL.createObjectURL(blob);
+  const a = document.createElement('a');
+  a.href = url;
+  a.download = fileName;
+  document.body.appendChild(a);
+  a.click();
+  window.URL.revokeObjectURL(url);
+  document.body.removeChild(a);
+};
+
+/**
+ * 消息弹窗框
+ * @param message 消息弹窗框提示
+ * @param title 消息弹窗框标题
+ * @param type type 类型
+ * @param options 消息弹窗框其他配置
+ * @returns promise
+ */
+export function confirmAction(message: string, title = '', type: componentType = 'warning', options = {}) {  
+  return new Promise<void>((resolve, reject) => {  
+    ElMessageBox.confirm(message, title, {  
+      ...{  
+        confirmButtonText: '确定',  
+        cancelButtonText: '取消',  
+        type: type,  
+      },  
+      ...options,  
+    })  
+      .then(() => resolve())  
+      .catch(() => reject());  
+  });  
+}
+
 /**
  * 返回上一级
  */

Plik diff jest za duży
+ 33330 - 16130
fhKeeper/formulahousekeeper/management-crm/crm.log


+ 21 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ActionLogController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-26
+ */
+@RestController
+@RequestMapping("/action-log")
+public class ActionLogController {
+
+}
+

+ 21 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/BusinessItemCustomController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-02
+ */
+@RestController
+@RequestMapping("/business-item-custom")
+public class BusinessItemCustomController {
+
+}
+

+ 109 - 12
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/BusinessOpportunityController.java

@@ -1,21 +1,26 @@
 package com.management.platform.controller;
 
 
-import com.management.platform.entity.BusinessOpportunity;
-import com.management.platform.entity.User;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.management.platform.entity.*;
+import com.management.platform.mapper.BusinessOpportunityMapper;
 import com.management.platform.mapper.UserMapper;
 import com.management.platform.service.BusinessOpportunityService;
+import com.management.platform.service.StageService;
 import com.management.platform.service.SysFunctionService;
+import com.management.platform.service.TaskService;
 import com.management.platform.util.HttpRespMsg;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 
@@ -35,75 +40,167 @@ public class BusinessOpportunityController {
     private UserMapper userMapper;
     @Resource
     private SysFunctionService sysFunctionService;
+    @Resource
+    private StageService stageService;
 
     @Resource
     private BusinessOpportunityService bOservice;
 
 
+    @RequestMapping("exportData")
+    public Object exportData(BusinessOpportunity bo, HttpServletRequest request) throws Exception {
+        return bOservice.exportData(bo,request);
+    }
+
     @RequestMapping("insertAndUpdate")
-    public HttpRespMsg insertAndUpdate(@RequestBody BusinessOpportunity bo, HttpServletRequest request) {
+    public HttpRespMsg insertAndUpdate( BusinessOpportunity bo, HttpServletRequest request) {
         User user = userMapper.selectById(request.getHeader("Token"));
         HttpRespMsg msg = new HttpRespMsg();
         if (bo.getId() == null){
             //新增
             bo.setCompanyId(user.getCompanyId());
             bo.setCreatorId(user.getId());
+            bo.setUserId(user.getId());
+            bo.setCreateTime(new Date());
             bOservice.insert(bo);
         }else {
             //修改
-            bOservice.update(bo);
+            bOservice.update(bo,user.getId());
         }
         msg.setMsg("操作成功");
         return msg;
     }
 
+    @RequestMapping("claim")
+    public Object claim(BusinessOpportunity bo, HttpServletRequest request) {
+        User user = userMapper.selectById(request.getHeader("Token"));
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.setMsg("操作成功");
+        bOservice.getAndTransfer(bo, user);
+        return msg;
+    }
     @RequestMapping("list")
-    public HashMap<Object, Object> list(@RequestBody BusinessOpportunity bo, HttpServletRequest request) {
+    public HttpRespMsg list(BusinessOpportunity bo, HttpServletRequest request) {
         HashMap<Object, Object> r = new HashMap<>();
         User user = userMapper.selectById(request.getHeader("Token"));
         bo.setIsDelete(0);
         bo.setCompanyId(user.getCompanyId());
+        bo.setUserId(user.getId());
+        bo.setEndTime(bo.getEndTime() + " 23:59:59");
+        bo.setPageIndex((bo.getPageIndex()-1) * bo.getPageFrom());
         List<BusinessOpportunity> list = new ArrayList<>();
         boolean isAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部商机");
         boolean isNotAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看负责部门商机");
         int i = 0;
-        if (!isAll) {
+        if (isAll) {
             list = bOservice.getAll(bo);
             i = bOservice.getTotal(bo);
-        } else if (!isNotAll) {
+        } else if (isNotAll) {
             list = bOservice.getAll1(bo, user);
             i = bOservice.getTotal1(bo, user);
         } else {
             list = bOservice.getAll2(bo, user);
+            i = bOservice.getTotal2(bo, user);
         }
         r.put("data", list);
         r.put("total",i);
-        return r;
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.setData(r);
+        return msg;
 
     }
     @RequestMapping("deleterList")
-    public HashMap<Object, Object> deleterList(@RequestBody BusinessOpportunity bo, HttpServletRequest request) {
+    public HttpRespMsg deleterList(BusinessOpportunity bo, HttpServletRequest request) {
         HashMap<Object, Object> r = new HashMap<>();
         User user = userMapper.selectById(request.getHeader("Token"));
         bo.setIsDelete(1);
+        bo.setUserId(user.getId());
         bo.setCompanyId(user.getCompanyId());
+        setNull(bo);
         List<BusinessOpportunity> list = new ArrayList<>();
         boolean isAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部商机");
         boolean isNotAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看负责部门商机");
         int i = 0;
-        if (!isAll) {
+        if (isAll) {
             list = bOservice.getAll(bo);
             i = bOservice.getTotal(bo);
-        } else if (!isNotAll) {
+        } else if (isNotAll) {
             list = bOservice.getAll1(bo, user);
             i = bOservice.getTotal1(bo, user);
         } else {
             list = bOservice.getAll2(bo, user);
+            i = bOservice.getTotal2(bo, user);
         }
         r.put("data", list);
         r.put("total",i);
-        return r;
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.setData(r);
+        return msg;
+    }
+    @RequestMapping("getInfo")
+    public HttpRespMsg getInfo(BusinessOpportunity bo ,HttpServletRequest request) {
+        User user = userMapper.selectById(request.getHeader("Token"));
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.setData(bOservice.getInfo(bo,user));
+        return msg;
+    }
+    @RequestMapping("saveProduct")
+    public HttpRespMsg saveProduct(BusinessOpportunity bo , HttpServletRequest request) {
+        User user = userMapper.selectById(request.getHeader("Token"));
+        return bOservice.saveProduct(bo,user);
+    }
+
+    @RequestMapping("saveStage")
+    public HttpRespMsg insertStage(List<Stage> stages, HttpServletRequest request) {
+        return stageService.changeStage(stages);
+    }
+    @RequestMapping("getStage")
+    public HttpRespMsg Stage() {
+        return stageService.getStage();
+    }
+
+    private BusinessOpportunity setNull(BusinessOpportunity bo) {
+        if (bo.getPlate1() == "") {
+            bo.setPlate1(null);
+        }
+        if (bo.getPlate2() == "") {
+            bo.setPlate2(null);
+        }
+        if (bo.getPlate3() == "") {
+            bo.setPlate3(null);
+        }
+        if (bo.getPlate4() == "") {
+            bo.setPlate4(null);
+        }
+        if (bo.getPlate5() == "") {
+            bo.setPlate5(null);
+        }
+        return bo;
+    }
+
+
+    // 上传
+    @RequestMapping("uploadFile")
+    public Object uploadFile(BusinessItemCustom bo, HttpServletRequest request, MultipartFile file) throws Exception {
+        return bOservice.uploadFile(bo, request, file);
+    }
+
+    //下载
+    @RequestMapping("downFile")
+    public Object downFile(UploadFile file, HttpServletRequest request, HttpServletResponse response) throws Exception {
+        return bOservice.downFile(file, request, response);
+    }
+
+    //删除
+    @RequestMapping("deleteFile")
+    public Object downFile(UploadFile file, HttpServletRequest request) throws Exception {
+        return bOservice.deleteFile(file, request);
+    }
 
+    //重命名
+    @RequestMapping("reFileName")
+    public Object reFileName(UploadFile uploadFile, HttpServletRequest request) throws Exception {
+        return bOservice.reFileName(uploadFile, request);
     }
 
 

+ 21 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/BusinessProductController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-29
+ */
+@RestController
+@RequestMapping("/business-product")
+public class BusinessProductController {
+
+}
+

+ 102 - 26
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ClueController.java

@@ -4,6 +4,7 @@ package com.management.platform.controller;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.management.platform.entity.Clue;
 import com.management.platform.entity.SysDict;
+import com.management.platform.entity.UploadFile;
 import com.management.platform.entity.User;
 import com.management.platform.mapper.SysDictMapper;
 import com.management.platform.mapper.SysFunctionMapper;
@@ -17,9 +18,12 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -47,6 +51,7 @@ public class ClueController {
     private SysDictMapper sysDictMapper;
 
 
+    // 详情
     @RequestMapping("getDetail")
     public Object getDetail(Clue clue) {
         HttpRespMsg msg = new HttpRespMsg();
@@ -54,40 +59,72 @@ public class ClueController {
         return msg;
     }
 
+    // 导入
+    @RequestMapping("exportData")
+    public Object exportData(Clue clue, HttpServletRequest request) throws Exception {
+        return clueService.exportData(clue, request);
+    }
+
+    // 上传
+    @RequestMapping("uploadFile")
+    public Object uploadFile(Clue clue, HttpServletRequest request, MultipartFile file) throws Exception {
+        return clueService.uploadFile(clue, request, file);
+    }
+
+    //下载
+//    @RequestMapping("downFile")
+//    public Object downFile(UploadFile file, HttpServletRequest request, HttpServletResponse response) throws Exception {
+//        return clueService.downFile(file, request, response);
+//    }
+
+    //删除
+    @RequestMapping("deleteFile")
+    public Object downFile(UploadFile file, HttpServletRequest request) throws Exception {
+        return clueService.deleteFile(file, request);
+    }
+
+    //重命名
+    @RequestMapping("reFileName")
+    public Object reFileName(UploadFile uploadFile, HttpServletRequest request) throws Exception {
+        return clueService.reFileName(uploadFile, request);
+    }
+
+
+
     @RequestMapping("listClue")
     public Object list(Clue clue, HttpServletRequest request) {
-        //TODO token待定
         User user = userMapper.selectById(request.getHeader("Token"));
         clue.setCompanyId(user.getCompanyId());
         clue.setIsDelete(0);
         clue.setEndTime(clue.getEndTime() + " 23:59:59");
-        clue.setPageIndex((clue.getPageIndex()-1) * clue.getPageFrom() );
+        clue.setPageIndex((clue.getPageIndex() - 1) * clue.getPageFrom());
         boolean isAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部线索");
         boolean isNotAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看负责部门线索");
         List<Clue> list = new ArrayList<>();
         int i = 0;
-        if (!isAll) {
+        if (isAll) {
             //查看全部线索
             list = clueService.getList(clue);
             i = clueService.getTotal(clue);
-        } else if (!isNotAll) {
+        } else if (isNotAll) {
             //查看负责部门线索 找出所处部门下所有的负责人
             list = clueService.getList1(clue, user);
-            i = clueService.getTotal1(clue,user);
+            i = clueService.getTotal1(clue, user);
         } else {
             // 查看负责人为 自己 和 null的数据
             list = clueService.getList2(clue, user);
-            i = clueService.getTotal2(clue,user);
+            i = clueService.getTotal2(clue, user);
         }
         HashMap<Object, Object> map = new HashMap<>();
         map.put("data", list);
         map.put("total", i);
-        return map;
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.setData(map);
+        return msg;
     }
 
     @RequestMapping("listDeleterClue")
-    public Object listDeleterClue(@RequestBody Clue clue, HttpServletRequest request) {
-        //TODO token待定
+    public Object listDeleterClue(Clue clue, HttpServletRequest request) {
         User user = userMapper.selectById(request.getHeader("Token"));
         clue.setCompanyId(user.getCompanyId());
         boolean isAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部线索");
@@ -95,31 +132,36 @@ public class ClueController {
         List<Clue> list = new ArrayList<>();
         clue.setIsDelete(1);
         int i = 0;
-        if (!isAll) {
+        if (isAll) {
             //查看全部线索
             list = clueService.getList(clue);
             i = clueService.getTotal(clue);
-        } else if (!isNotAll) {
+        } else if (isNotAll) {
             //查看负责部门线索 找出所处部门下所有的负责人
             list = clueService.getList1(clue, user);
-            i = clueService.getTotal1(clue,user);
+            i = clueService.getTotal1(clue, user);
         } else {
             // 查看负责人为 自己 和 null的数据
             list = clueService.getList2(clue, user);
-            i = clueService.getTotal2(clue,user);
+            i = clueService.getTotal2(clue, user);
         }
         HashMap<Object, Object> map = new HashMap<>();
         map.put("data", list);
-        map.put("total",i);
-        return map;
+        map.put("total", i);
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        httpRespMsg.setData(map);
+        return httpRespMsg;
     }
 
     @RequestMapping("/insertAndUpdate")
-    public Object inserANdUpdate(@RequestBody Clue clue, HttpServletRequest request) {
+    public Object inserANdUpdate(Clue clue, HttpServletRequest request) {
         HttpRespMsg msg = new HttpRespMsg();
         //操作前校验
-        //TODO token待定
         User user = userMapper.selectById(request.getHeader("Token"));
+        if (user == null) {
+            msg.setError("获取创建人失败");
+            return msg;
+        }
         clue.setCompanyId(user.getCompanyId());
         if (null == clue.getClueName() || "".equals(clue.getClueName())) {
             msg.setError("线索名称不能为空");
@@ -144,24 +186,48 @@ public class ClueController {
     }
 
 
+    // 批量放入回收站
     @RequestMapping("delete")
-    public Object delete(@RequestBody List<Integer> ids) {
+    public Object delete(Clue clue) {
         HttpRespMsg msg = new HttpRespMsg();
-        msg.setMsg("操作成功");
-        clueService.isDelete(ids);
+        String ids1 = clue.getIds();
+        List<Integer> ids = new ArrayList<>();
+        if (!ids1.isEmpty()) {
+            for (String id : ids1.split(",")) {
+                ids.add(Integer.parseInt(id));
+            }
+            clueService.isDelete(ids);
+            msg.setMsg("操作成功");
+        } else {
+            msg.setError("请选择线索");
+
+        }
         return msg;
     }
 
+    // 批量恢复
     @RequestMapping("rollback")
-    public Object rollback(@RequestBody List<Integer> ids) {
+    public Object rollback(Clue clue) {
         HttpRespMsg msg = new HttpRespMsg();
         msg.setMsg("操作成功");
-        clueService.isRollback(ids);
+        String ids1 = clue.getIds();
+        List<Integer> ids = new ArrayList<>();
+        if (!ids1.isEmpty()) {
+            for (String id : ids1.split(",")) {
+                ids.add(Integer.parseInt(id));
+            }
+            clueService.isRollback(ids);
+            msg.setMsg("操作成功");
+        } else {
+            msg.setError("请选择线索");
+
+        }
         return msg;
     }
 
+    // 认领&转移线索
     @RequestMapping("claim")
-    public Object claim(@RequestBody Clue clue, HttpServletRequest request) {
+    public Object claim(Clue clue, HttpServletRequest request) {
         User user = userMapper.selectById(request.getHeader("Token"));
         HttpRespMsg msg = new HttpRespMsg();
         msg.setMsg("操作成功");
@@ -169,11 +235,21 @@ public class ClueController {
         return msg;
     }
 
+    //回收站内删除
     @RequestMapping("deleterDelete")
-    public Object deleterDelete(@RequestBody List<Integer> ids) {
+    public Object deleterDelete(Clue clue) {
         HttpRespMsg msg = new HttpRespMsg();
-        msg.setMsg("操作成功");
-        clueService.deleterDelete(ids);
+        String ids1 = clue.getIds();
+        List<Integer> ids = new ArrayList<>();
+        if (!ids1.isEmpty()) {
+            for (String id : ids1.split(",")) {
+                ids.add(Integer.parseInt(id));
+            }
+            clueService.deleterDelete(ids);
+            msg.setMsg("操作成功");
+        } else {
+            msg.setError("请选择线索");
+        }
         return msg;
     }
 

+ 21 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/ClueUploadfileController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-25
+ */
+@RestController
+@RequestMapping("/clue-uploadfile")
+public class ClueUploadfileController {
+
+}
+

+ 134 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/CustomController.java

@@ -1,9 +1,24 @@
 package com.management.platform.controller;
 
 
+import com.management.platform.entity.Clue;
+import com.management.platform.entity.Custom;
+import com.management.platform.entity.UploadFile;
+import com.management.platform.entity.User;
+import com.management.platform.mapper.UserMapper;
+import com.management.platform.service.CustomService;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * <p>
@@ -16,6 +31,125 @@ import org.springframework.web.bind.annotation.RestController;
 @RestController
 @RequestMapping("/custom")
 public class CustomController {
+    @Value(value = "${upload.file}")
+    private String file;
+    @Autowired
+    private CustomService customService;
+    @Autowired
+    private UserMapper userMapper;
+
+    @RequestMapping("list")
+    public HttpRespMsg list(Custom custom , HttpServletRequest request){
+        return customService.getList(custom,request);
+    }
+    @RequestMapping("deleteList")
+    public HttpRespMsg deleteList(Custom custom , HttpServletRequest request){
+        return customService.getDeleteList(custom,request);
+    }
+
+
+    @RequestMapping("insertAndUpdate")
+    public HttpRespMsg insertAndUpdate(Custom custom , HttpServletRequest request){
+        return customService.insertAndUpdate(custom,request);
+    }
+    @RequestMapping("getInfo")
+    public HttpRespMsg getInfo(Custom custom , HttpServletRequest request){
+        return customService.getInfo(custom,request);
+    } @RequestMapping("getLog")
+    public HttpRespMsg getLog(Custom custom , HttpServletRequest request){
+        return customService.getInfo(custom,request);
+    }
+
+
+    // 批量放入回收站
+    @RequestMapping("deleter")
+    public Object delete(Custom custom) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String ids1 = custom.getIds();
+        List<Integer> ids = new ArrayList<>();
+        if (!ids1.isEmpty()) {
+            for (String id : ids1.split(",")) {
+                ids.add(Integer.parseInt(id));
+            }
+            customService.isDelete(ids);
+            msg.setMsg("操作成功");
+        }else {
+            msg.setError("请选择客户");
+
+        }
+        return msg;
+    }
+    // 批量恢复
+    @RequestMapping("rollback")
+    public Object rollback(Custom custom) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String ids1 = custom.getIds();
+        List<Integer> ids = new ArrayList<>();
+        if (!ids1.isEmpty()) {
+            for (String id : ids1.split(",")) {
+                ids.add(Integer.parseInt(id));
+            }
+            customService.isRollback(ids);
+            msg.setMsg("操作成功");
+        }else {
+            msg.setError("请选择客户");
+
+        }
+        return msg;
+    }
+    //彻底删除
+    @RequestMapping("reallyDelete")
+    public Object reallyDelete(Custom custom) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String ids1 = custom.getIds();
+        List<Integer> ids = new ArrayList<>();
+        if (!ids1.isEmpty()) {
+            for (String id : ids1.split(",")) {
+                ids.add(Integer.parseInt(id));
+            }
+            customService.isReallyDelete(ids);
+            msg.setMsg("操作成功");
+        }else {
+            msg.setError("请选择客户");
+
+        }
+        return msg;
+    }
+
+    // 认领&转移线索
+    @RequestMapping("claim")
+    public Object claim(Custom custom, HttpServletRequest request) {
+        User user = userMapper.selectById(request.getHeader("Token"));
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.setMsg("操作成功");
+        customService.getAndTransfer(custom, user);
+        return msg;
+    }
+
+    // 上传
+    @RequestMapping("uploadFile")
+    public Object uploadFile(Custom custom, HttpServletRequest request, MultipartFile file) throws Exception {
+        return customService.uploadFile(custom, request, file);
+    }
+
+    //下载
+    @RequestMapping("downFile")
+    public Object downFile(UploadFile file, HttpServletRequest request, HttpServletResponse response) throws Exception {
+        return customService.downFile(file, request, response);
+    }
+
+    //删除
+    @RequestMapping("deleteFile")
+    public Object downFile(UploadFile file, HttpServletRequest request) throws Exception {
+        return customService.deleteFile(file, request);
+    }
+
+    //重命名
+    @RequestMapping("reFileName")
+    public Object reFileName(UploadFile uploadFile, HttpServletRequest request) throws Exception {
+        return customService.reFileName(uploadFile, request);
+    }
+
 
 }
 

+ 21 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/CustomItemContactsController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-02
+ */
+@RestController
+@RequestMapping("/custom-item-contacts")
+public class CustomItemContactsController {
+
+}
+

+ 89 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/OrderController.java

@@ -1,9 +1,28 @@
 package com.management.platform.controller;
 
 
+import com.alibaba.fastjson.JSONArray;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.management.platform.entity.Order;
+import com.management.platform.entity.OrderProductDetail;
+import com.management.platform.entity.Product;
+import com.management.platform.entity.Task;
+import com.management.platform.mapper.UserMapper;
+import com.management.platform.service.OrderProductDetailService;
+import com.management.platform.service.OrderService;
+import com.management.platform.service.ProductService;
+import com.management.platform.service.TaskService;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.RequestMapping;
 
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
 
 /**
  * <p>
@@ -16,6 +35,76 @@ import org.springframework.web.bind.annotation.RestController;
 @RestController
 @RequestMapping("/order")
 public class OrderController {
+    @Resource
+    private OrderService orderService;
+    @Resource
+    private UserMapper userMapper;
+    @Resource
+    private HttpServletRequest request;
+    @Resource
+    private OrderProductDetailService orderProductDetailService;
+
+    @RequestMapping("/list")
+    public HttpRespMsg list(String userId, String orderName,String orderCode, String productCode, Integer pageIndex, Integer pageSize,Integer isDelete){
+        return orderService.getList(userId,orderName,orderCode,productCode,pageIndex,pageSize,isDelete);
+    }
+
+    @RequestMapping("/addOrUpdate")
+    public HttpRespMsg addOrUpdate(Order order){
+        HttpRespMsg msg=new HttpRespMsg();
+        Integer companyId = userMapper.selectById(request.getHeader("token")).getCompanyId();
+        order.setCompanyId(companyId);
+        int count;
+        if(order.getId()==null){
+            count = orderService.count(new LambdaQueryWrapper<Order>().eq(Order::getCompanyId, companyId).eq(Order::getOrderCode, order.getOrderCode()));
+        }else {
+            count = orderService.count(new LambdaQueryWrapper<Order>().eq(Order::getCompanyId, companyId).ne(Order::getId,order.getId()).eq(Order::getOrderCode,order.getOrderCode()));
+        }
+        if(count>0){
+            msg.setError("订单编号为["+order.getOrderCode()+"]的订单已存在");
+            return msg;
+        }
+        if(!orderService.saveOrUpdate(order)){
+            msg.setError("验证失败");
+            return msg;
+        }
+        //处理订单下的产品数据
+        if(!StringUtils.isEmpty(order.getOrderProductDetailString())){
+            String orderProductDetailString = order.getOrderProductDetailString();
+            List<OrderProductDetail> orderProductDetails = JSONArray.parseArray(orderProductDetailString, OrderProductDetail.class);
+            if(orderProductDetails.size()>0){
+                orderProductDetails.forEach(o->{
+                    o.setOrderId(order.getId());
+                });
+                orderProductDetailService.saveOrUpdateBatch(orderProductDetails);
+            }
+        }
+        return msg;
+    }
+
+    @RequestMapping("/delete")
+    public HttpRespMsg delete(Integer id){
+        HttpRespMsg msg=new HttpRespMsg();
+        Order order = orderService.getById(id);
+        order.setIsDelete(1);
+        if(!orderService.updateById(order)){
+            msg.setError("验证失败");
+            return msg;
+        }
+        return msg;
+    }
+
+    @RequestMapping("/recover")
+    public HttpRespMsg recover(Integer id){
+        HttpRespMsg msg=new HttpRespMsg();
+        Order order = orderService.getById(id);
+        order.setIsDelete(0);
+        if(!orderService.updateById(order)){
+            msg.setError("验证失败");
+            return msg;
+        }
+        return msg;
+    }
 
 }
 

+ 21 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/OrderProductDetailController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-03
+ */
+@RestController
+@RequestMapping("/order-product-detail")
+public class OrderProductDetailController {
+
+}
+

+ 21 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/SeqController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-02
+ */
+@RestController
+@RequestMapping("/seq")
+public class SeqController {
+
+}
+

+ 21 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/StageController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-29
+ */
+@RestController
+@RequestMapping("/stage")
+public class StageController {
+
+}
+

+ 10 - 5
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/TaskController.java

@@ -53,22 +53,22 @@ public class TaskController {
 
 
     @RequestMapping("addTask")
-    public HttpRespMsg addTask(@RequestBody TaskDto taskDto){
+    public HttpRespMsg addTask(TaskDto taskDto){
         return taskService.addTask(taskDto, request);
     }
 
     @RequestMapping("pageTask")
-    public HttpRespMsg pageTask(@RequestBody TaskDto taskDto){
+    public HttpRespMsg pageTask(TaskDto taskDto){
         return taskService.pageTask(taskDto,request);
     }
 
     @RequestMapping("updateTask")
-    public HttpRespMsg updateTask(@RequestBody TaskDto taskDto){
+    public HttpRespMsg updateTask( TaskDto taskDto){
         return taskService.updateTask(taskDto ,request);
     }
 
     @RequestMapping("deleteTasks")
-    public HttpRespMsg deleteTasks(@RequestBody List<Integer> taskIds){
+    public HttpRespMsg deleteTasks(List<Integer> taskIds){
         return taskService.deleteTasks(taskIds);
     }
 
@@ -78,9 +78,14 @@ public class TaskController {
     }
 
     @RequestMapping("exportData")
-    public HttpRespMsg exportData(@RequestBody TaskDto taskDto) throws Exception {
+    public HttpRespMsg exportData(TaskDto taskDto) throws Exception {
         return taskService.exportData(taskDto,request);
     }
 
+    @RequestMapping("updateTaskStatus")
+    public HttpRespMsg updateTaskStatus(TaskDto taskDto) throws Exception {
+        return taskService.updateTaskStatus(taskDto,request);
+    }
+
 }
 

+ 21 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/UploadFileController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-26
+ */
+@RestController
+@RequestMapping("/upload-file")
+public class UploadFileController {
+
+}
+

+ 71 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/ActionLog.java

@@ -0,0 +1,71 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import java.util.Date;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-26
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class ActionLog extends Model<ActionLog> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 模块id
+     */
+    @TableField("item_id")
+    private Integer itemId;
+
+    /**
+     * 操作时间
+     */
+    @TableField("creat_time")
+    private Date creatTime;
+
+    /**
+     * 操作内容
+     */
+    @TableField("name")
+    private String name;
+    @TableField(exist = false)
+    private String userName;
+
+    /**
+     * 创建人id
+     */
+    @TableField("user_id")
+    private String userId;
+
+    /**
+     * 模块代码
+     */
+    @TableField("code")
+    private String code;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 48 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/BusinessItemCustom.java

@@ -0,0 +1,48 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-02
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class BusinessItemCustom extends Model<BusinessItemCustom> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 客户id
+     */
+    @TableField("contacts_id")
+    private Integer contactsId;
+
+    /**
+     * 联系人id
+     */
+    @TableField("business_id")
+    private Integer businessId;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 10 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/BusinessItemProduct.java

@@ -35,6 +35,16 @@ public class BusinessItemProduct extends Model<BusinessItemProduct> {
      */
     @TableField("product_id")
     private Integer productId;
+    @TableField(exist = false)
+    private String productName;
+    @TableField(exist = false)
+    private String unit;
+    @TableField(exist = false)
+    private BigDecimal price;
+    @TableField(exist = false)
+    private String inventory;
+    @TableField(exist = false)
+    private String productType;
 
     /**
      * 商机id

+ 42 - 9
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/BusinessOpportunity.java

@@ -3,10 +3,13 @@ package com.management.platform.entity;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import com.baomidou.mybatisplus.annotation.TableId;
+
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import com.baomidou.mybatisplus.annotation.TableField;
 import java.io.Serializable;
 import java.util.Date;
+import java.util.List;
 
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -18,7 +21,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2024-03-13
+ * @since 2024-03-22
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -33,9 +36,7 @@ public class BusinessOpportunity extends Model<BusinessOpportunity> {
     @TableField("company_id")
     private Integer companyId;
 
-    private Integer productId;
-
-
+    @TableField(exist = false)
     private String productName;
 
     /**
@@ -49,13 +50,21 @@ public class BusinessOpportunity extends Model<BusinessOpportunity> {
      */
     @TableField("contacts_id")
     private Integer contactsId;
+    @TableField(exist = false)
+    private Integer contactsName;
 
     /**
      * 客户id
      */
     @TableField("customer_id")
     private Integer customerId;
+    @TableField(exist = false)
     private String customerName;
+    /**
+     * 产品id
+     */
+    @TableField("product_id")
+    private Integer productId;
 
     /**
      * 商机金额
@@ -72,33 +81,41 @@ public class BusinessOpportunity extends Model<BusinessOpportunity> {
     /**
      * 商机阶段 0-验证客户 1-需求分析 2-方案报价 3-赢单
      */
-    @TableField("stage")
-    private Integer stage;
+    @TableField("stage_id")
+    private Integer stageId;
+    @TableField(exist = false)
+    private String stageValue;
+    @TableField(exist = false)
+    private String total;
 
     /**
      * 创建时间
      */
     @TableField("create_time")
     private Date createTime;
-    private Date startTime;
-    private Date endTIme;
+    @TableField(exist = false)
+    private String startTime;
+    @TableField(exist = false)
+    private String endTime;
     /**
      * 修改时间
      */
     @TableField("edit_time")
-    private LocalDateTime editTime;
+    private Date editTime;
 
     /**
      * 创建人
      */
     @TableField("creator_id")
     private String creatorId;
+    @TableField(exist = false)
     private String creatorName;
     /**
      * 负责人
      */
     @TableField("incharger_id")
     private String inchargerId;
+    @TableField(exist = false)
     private String inchargerName;
 
     /**
@@ -106,13 +123,19 @@ public class BusinessOpportunity extends Model<BusinessOpportunity> {
      */
     @TableField("remark")
     private String remark;
+    @TableField(exist = false)
+    private String ids;
+    @TableField(exist = false)
+    private BigDecimal finalPrice;
 
     /**
      * 回收站(是否删除) 0-否 1-是
      */
     @TableField("is_delete")
     private Integer isDelete;
+    @TableField(exist = false)
     private Integer pageIndex;
+    @TableField(exist = false)
     private Integer pageFrom;
 
     /**
@@ -120,6 +143,8 @@ public class BusinessOpportunity extends Model<BusinessOpportunity> {
      */
     @TableField("plate1")
     private String plate1;
+    @TableField(exist = false)
+    private String userId;
 
     /**
      * 自定义字段存值
@@ -144,6 +169,14 @@ public class BusinessOpportunity extends Model<BusinessOpportunity> {
      */
     @TableField("plate5")
     private String plate5;
+    @TableField(exist = false)
+    private List<BusinessItemProduct> businessItemProductList;
+    @TableField(exist = false)
+    private List<ActionLog> actionLogList;
+    @TableField(exist = false)
+    private List<Task> taskList;
+    @TableField(exist = false)
+    private List<UploadFile> uploadFilePList;
 
 
 

+ 73 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/BusinessProduct.java

@@ -0,0 +1,73 @@
+package com.management.platform.entity;
+
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-29
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class BusinessProduct extends Model<BusinessProduct> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 产品id
+     */
+    @TableField("product_id")
+    private Integer productId;
+
+    /**
+     * 商机id
+     */
+    @TableField("business_id")
+    private Integer businessId;
+
+    /**
+     * 售价
+     */
+    @TableField("selling_price")
+    private BigDecimal sellingPrice;
+
+    /**
+     * 数量
+     */
+    @TableField("count")
+    private Integer count;
+
+    /**
+     * 折扣
+     */
+    @TableField("discount")
+    private BigDecimal discount;
+
+    /**
+     * 合计
+     */
+    @TableField("total")
+    private BigDecimal total;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 23 - 6
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Clue.java

@@ -8,7 +8,6 @@ import java.io.Serializable;
 import java.util.Date;
 import java.util.List;
 
-import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
@@ -39,6 +38,8 @@ public class Clue extends Model<Clue> {
     //创建人
     @TableField("create_id")
     private String createId;
+    @TableField(exist = false)
+    private String createName;
 
     /**
      * 线索名称
@@ -46,6 +47,7 @@ public class Clue extends Model<Clue> {
     @TableField("clue_name")
     private String clueName;
 
+    @TableField(exist = false)
     private String companyName;
 
     /**
@@ -53,6 +55,8 @@ public class Clue extends Model<Clue> {
      */
     @TableField("clue_source_id")
     private Integer clueSourceId;
+    @TableField(exist = false)
+    private String clueSourceValue;
 
     /**
      * 电话
@@ -70,18 +74,24 @@ public class Clue extends Model<Clue> {
      */
     @TableField("customer_industry_id")
     private Integer customerIndustryId;
+    @TableField(exist = false)
+    private String customerIndustryValue;
 
     /**
      * 客户级别
      */
     @TableField("customer_level_id")
     private Integer customerLevelId;
+    @TableField(exist = false)
+    private String customerLevelValue;
 
     /**
      * 地址
      */
     @TableField("address")
     private String address;
+    @TableField(exist = false)
+    private String ids;
 
 
     /**
@@ -89,6 +99,8 @@ public class Clue extends Model<Clue> {
      */
     @TableField("incharger_id")
     private String inchargerId;
+    @TableField(exist = false)
+    private String inchargerName;
 
 
 //    private String tempInchargerId;
@@ -140,15 +152,20 @@ public class Clue extends Model<Clue> {
      */
     @TableField("create_time")
     private Date createTime;
+    @TableField(exist = false)
     private String startTime;
-
+    @TableField(exist = false)
     private String endTime;
-
+    @TableField(exist = false)
     private Integer pageIndex;
+    @TableField(exist = false)
     private Integer pageFrom;
-
-    private List<ClueLog> clueLogList;
-
+    @TableField(exist = false)
+    private List<ActionLog> clueLogList;
+    @TableField(exist = false)
+    private List<UploadFile> files;
+    @TableField(exist = false)
+    private List<Task> taskList;
 
 
     @Override

+ 68 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/ClueUploadfile.java

@@ -0,0 +1,68 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import java.util.Date;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-25
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class ClueUploadfile extends Model<ClueUploadfile> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 名称
+     */
+    @TableField("name")
+    private String name;
+
+    /**
+     * 文件地址
+     */
+    @TableField("path")
+    private String path;
+    /**
+     * 上传人
+     */
+    @TableField("create_id")
+    private String createId;
+
+    /**
+     * 线索id
+     */
+    @TableField("clue_id")
+    private Integer clueId;
+
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    private Date createTime;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 6 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Contacts.java

@@ -39,6 +39,8 @@ public class Contacts extends Model<Contacts> {
      */
     @TableField("sex")
     private Integer sex;
+    @TableField(exist = false)
+    private String sexValue;
 
     /**
      * 联系人名称
@@ -69,12 +71,16 @@ public class Contacts extends Model<Contacts> {
      */
     @TableField("owner_id")
     private String ownerId;
+    @TableField(exist = false)
+    private String ownerName;
 
     /**
      * 创建人
      */
     @TableField("creator_id")
     private String creatorId;
+    @TableField(exist = false)
+    private String creatorName;
 
     /**
      * 地址

+ 59 - 6
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Custom.java

@@ -3,27 +3,33 @@ package com.management.platform.entity;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
 import com.baomidou.mybatisplus.annotation.TableId;
+
 import java.time.LocalDateTime;
+
 import com.baomidou.mybatisplus.annotation.TableField;
+
 import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
 
 /**
  * <p>
- * 
+ *
  * </p>
  *
  * @author Seyason
- * @since 2024-02-28
+ * @since 2024-03-22
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
 @Accessors(chain = true)
 public class Custom extends Model<Custom> {
 
-    private static final long serialVersionUID=1L;
+    private static final long serialVersionUID = 1L;
 
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
@@ -36,24 +42,47 @@ public class Custom extends Model<Custom> {
      */
     @TableField("custom_name")
     private String customName;
+    /**
+     * 地址
+     */
+    @TableField("address")
+    private String address;
+    /**
+     * 负责人
+     */
+    @TableField("incharger_id")
+    private String inchargerId;
+    private String inchargerName;
+
+    /**
+     * 公司电话
+     */
+    @TableField("company_phone")
+    private String companyPhone;
 
     /**
      * 客户来源id
      */
     @TableField("custom_source_id")
     private Integer customSourceId;
+    @TableField(exist = false)
+    private String customSourceValue;
 
     /**
      * 客户行业id
      */
     @TableField("customer_industry_id")
     private Integer customerIndustryId;
+    @TableField(exist = false)
+    private Integer customerIndustryValue;
 
     /**
      * 客户级别id
      */
     @TableField("customer_level_id")
     private Integer customerLevelId;
+    @TableField(exist = false)
+    private String customerLevelValue;
 
     /**
      * 邮箱
@@ -66,6 +95,8 @@ public class Custom extends Model<Custom> {
      */
     @TableField("owner_id")
     private String ownerId;
+    @TableField(exist = false)
+    private String ownerName;
 
     /**
      * 客户编号
@@ -90,6 +121,8 @@ public class Custom extends Model<Custom> {
      */
     @TableField("country_billing")
     private String countryBilling;
+    @TableField(exist = false)
+    private String userId;
 
     /**
      * 开单地址-省/市
@@ -137,7 +170,7 @@ public class Custom extends Model<Custom> {
      * 创建时间
      */
     @TableField("create_time")
-    private LocalDateTime createTime;
+    private Date createTime;
 
     /**
      * 自定义字段存值
@@ -174,18 +207,38 @@ public class Custom extends Model<Custom> {
      */
     @TableField("creator_id")
     private String creatorId;
+    @TableField(exist = false)
+    private String creatorName;
 
     /**
      * 描述
      */
-    @TableField("desc")
-    private String desc;
+    @TableField("custom_desc")
+    private String customDesc;
 
     /**
      * 回收站(是否删除) 0-否 1-是
      */
     @TableField("is_delete")
     private Integer isDelete;
+    @TableField(exist = false)
+    private String ids;
+    @TableField(exist = false)
+    private String startTime;
+    @TableField(exist = false)
+    private String endTime;
+    @TableField(exist = false)
+    private Integer pageIndex;
+    @TableField(exist = false)
+    private Integer pageFrom;
+    @TableField(exist = false)
+    private List<UploadFile> files;
+    @TableField(exist = false)
+    private List<BusinessOpportunity> BusinessOpportunitys;
+    @TableField(exist = false)
+    private List<ActionLog> actionLogs;
+    @TableField(exist = false)
+    private List<Contacts> contactsList;
 
 
     @Override

+ 48 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/CustomItemContacts.java

@@ -0,0 +1,48 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-02
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class CustomItemContacts extends Model<CustomItemContacts> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 客户id
+     */
+    @TableField("contacts_id")
+    private Integer contactsId;
+
+    /**
+     * 联系人id
+     */
+    @TableField("custom_id")
+    private Integer customId;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 76 - 2
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Order.java

@@ -3,13 +3,18 @@ package com.management.platform.entity;
 import java.math.BigDecimal;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
+import java.time.LocalDate;
 import com.baomidou.mybatisplus.annotation.TableId;
 import java.time.LocalDateTime;
 import com.baomidou.mybatisplus.annotation.TableField;
 import java.io.Serializable;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
 
 /**
  * <p>
@@ -17,7 +22,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2024-02-28
+ * @since 2024-04-03
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -69,11 +74,35 @@ public class Order extends Model<Order> {
     private Integer contactsId;
 
     /**
-     * 类型
+     * 订单类型
      */
     @TableField("type")
     private Integer type;
 
+    /**
+     * 下单时间
+     */
+    @TableField("place_time")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime placeTime;
+
+    /**
+     * 订单开始时间
+     */
+    @TableField("order_start_date")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate orderStartDate;
+
+    /**
+     * 订单结束时间
+     */
+    @TableField("order_end_date")
+    @DateTimeFormat(pattern = "yyyy-MM-dd")
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private LocalDate orderEndDate;
+
     /**
      * 已回款金额
      */
@@ -86,18 +115,50 @@ public class Order extends Model<Order> {
     @TableField("un_received_payment")
     private BigDecimal unReceivedPayment;
 
+    /**
+     * 客户签约人
+     */
+    @TableField("custom_signer")
+    private String customSigner;
+
+    /**
+     * 公司签约人
+     */
+    @TableField("company_signer")
+    private String companySigner;
+
     /**
      * 负责人
      */
     @TableField("incharger_id")
     private String inchargerId;
 
+    /**
+     * 备注
+     */
+    @TableField("remark")
+    private String remark;
+
     @TableField("create_time")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
     @TableField("creator_id")
     private String creatorId;
 
+    /**
+     * 回收站(是否删除) 0-否 1-是
+     */
+    @TableField("is_delete")
+    private Integer isDelete;
+
+    /**
+     * 0-暂存 默认为1正常数据
+     */
+    @TableField("status")
+    private Integer status;
+
     /**
      * 自定义字段存值
      */
@@ -129,6 +190,19 @@ public class Order extends Model<Order> {
     private String plate5;
 
 
+    @TableField(exist = false)
+    private String orderProductDetailString;
+
+    @TableField(exist = false)
+    private List<OrderProductDetail> orderProductDetailList;
+
+    @TableField(exist = false)
+    private String typeName;
+
+    @TableField(exist = false)
+    private String inchargerName;
+
+
     @Override
     protected Serializable pkVal() {
         return this.id;

+ 58 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/OrderProductDetail.java

@@ -0,0 +1,58 @@
+package com.management.platform.entity;
+
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-03
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class OrderProductDetail extends Model<OrderProductDetail> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("order_id")
+    private Integer orderId;
+
+    @TableField("product_id")
+    private Integer productId;
+
+    /**
+     * 售价
+     */
+    @TableField("seal_price")
+    private BigDecimal sealPrice;
+
+    @TableField("num")
+    private BigDecimal num;
+
+    /**
+     * 折扣
+     */
+    @TableField("discount")
+    private Integer discount;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 7 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Product.java

@@ -20,7 +20,7 @@ import org.springframework.format.annotation.DateTimeFormat;
  * </p>
  *
  * @author Seyason
- * @since 2024-03-08
+ * @since 2024-03-29
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -65,6 +65,12 @@ public class Product extends Model<Product> {
     @TableField("price")
     private BigDecimal price;
 
+    /**
+     * 库存数量
+     */
+    @TableField("inventory")
+    private Integer inventory;
+
     /**
      * 状态 0-下架 1-上架
      */

+ 59 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Seq.java

@@ -0,0 +1,59 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-02
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class Seq extends Model<Seq> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId("id")
+    private Integer id;
+
+    /**
+     * 字段名称
+     */
+    @TableField("name")
+    private String name;
+
+    /**
+     * 顺序
+     */
+    @TableField("seq")
+    private String seq;
+
+    /**
+     * 是否为自定义 0否1是
+     */
+    @TableField("is_flag")
+    private Integer isFlag;
+
+    /**
+     * 模块
+     */
+    @TableField("code")
+    private String code;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 60 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Stage.java

@@ -0,0 +1,60 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-29
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class Stage extends Model<Stage> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 阶段名称
+     */
+    @TableField("name")
+    private String name;
+
+    /**
+     * 进度
+     */
+    @TableField("plan")
+    private String plan;
+
+    /**
+     * 顺序
+     */
+    @TableField("seq")
+    private Integer seq;
+
+    /**
+     * 是否为结束阶段
+     */
+    @TableField("is_finish")
+    private Integer isFinish;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 15 - 9
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/Task.java

@@ -2,10 +2,14 @@ package com.management.platform.entity;
 
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.extension.activerecord.Model;
+
 import java.time.LocalDate;
+
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableField;
+
 import java.io.Serializable;
+import java.util.Date;
 import java.util.List;
 
 import lombok.Data;
@@ -14,7 +18,7 @@ import lombok.experimental.Accessors;
 
 /**
  * <p>
- * 
+ *
  * </p>
  *
  * @author Seyason
@@ -25,7 +29,7 @@ import lombok.experimental.Accessors;
 @Accessors(chain = true)
 public class Task extends Model<Task> {
 
-    private static final long serialVersionUID=1L;
+    private static final long serialVersionUID = 1L;
 
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
@@ -35,6 +39,8 @@ public class Task extends Model<Task> {
      */
     @TableField("task_name")
     private String taskName;
+    @TableField(exist = false)
+    private String executorName;
 
     /**
      * 公司id
@@ -115,7 +121,7 @@ public class Task extends Model<Task> {
     private Integer repeatType;
 
     /**
-     * 重复永不结束   1:勾选  
+     * 重复永不结束   1:勾选
      */
     @TableField("repeat_end_never")
     private Integer repeatEndNever;
@@ -130,7 +136,7 @@ public class Task extends Model<Task> {
      * 重复结束 在  ? 日期YYYY-MM-DD之后
      */
     @TableField("repeat_end_date")
-    private LocalDate repeatEndDate;
+    private Date repeatEndDate;
 
     /**
      * 自定义周期: 每 ? 天一次,保存为 x1,x2,x3,x4
@@ -166,25 +172,25 @@ public class Task extends Model<Task> {
      * 创建时间
      */
     @TableField("create_date")
-    private LocalDate createDate;
+    private Date createDate;
 
     /**
      * 截止时间
      */
     @TableField("end_date")
-    private LocalDate endDate;
+    private Date endDate;
 
     /**
      * 开始日期
      */
     @TableField("start_date")
-    private LocalDate startDate;
+    private Date startDate;
 
     /**
      * 完成日期
      */
     @TableField("finish_date")
-    private LocalDate finishDate;
+    private Date finishDate;
 
     /**
      * 是否被删除: 0否,1是
@@ -221,7 +227,7 @@ public class Task extends Model<Task> {
      */
     @TableField("plate5")
     private String plate5;
-
+    @TableField(exist = false)
     private List<String> executorNames;
 
 

+ 4 - 1
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/TaskExecutor.java

@@ -15,7 +15,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2024-03-08
+ * @since 2024-03-22
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -27,6 +27,9 @@ public class TaskExecutor extends Model<TaskExecutor> {
     @TableId(value = "task_executor_id", type = IdType.AUTO)
     private Integer taskExecutorId;
 
+    @TableField("company_id")
+    private Integer companyId;
+
     @TableField("task_id")
     private Integer taskId;
 

+ 7 - 2
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/TaskLog.java

@@ -6,6 +6,8 @@ import com.baomidou.mybatisplus.annotation.TableId;
 import java.time.LocalDateTime;
 import com.baomidou.mybatisplus.annotation.TableField;
 import java.io.Serializable;
+import java.util.Date;
+
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
@@ -16,7 +18,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2021-05-04
+ * @since 2024-03-22
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -28,6 +30,9 @@ public class TaskLog extends Model<TaskLog> {
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
+    @TableField("company_id")
+    private Integer companyId;
+
     /**
      * 任务id
      */
@@ -38,7 +43,7 @@ public class TaskLog extends Model<TaskLog> {
      * 修改时间
      */
     @TableField("mod_time")
-    private LocalDateTime modTime;
+    private Date modTime;
 
     /**
      * 修改人

+ 84 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/UploadFile.java

@@ -0,0 +1,84 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import java.util.Date;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-26
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class UploadFile extends Model<UploadFile> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 名称
+     */
+    @TableField("name")
+    private String name;
+    /**
+     * 文件大小
+     */
+    @TableField("size")
+    private String size;
+    @TableField(exist = false)
+    private String userName;
+
+    /**
+     * 文件地址
+     */
+    @TableField("path")
+    private String path;
+    @TableField("real_name")
+    private String realName;
+
+    /**
+     * 对应模块id
+     */
+    @TableField("item_id")
+    private Integer itemId;
+
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    private Date createTime;
+
+    /**
+     * 创建人id
+     */
+    @TableField("create_id")
+    private String createId;
+
+    /**
+     * 模块码clue线索 business商户 custom客户
+     */
+    @TableField("code")
+    private String code;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 18 - 6
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/vo/TasKVo.java

@@ -7,17 +7,29 @@ import lombok.experimental.Accessors;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 @EqualsAndHashCode(callSuper = true)
 @Data
 @Accessors(chain = true)
 public class TasKVo extends Task {
-    private Custom custom;
-    private BusinessOpportunity businessOpportunity;
-    private Order order;
-    private Clue clue;
-    private Contacts contacts;
-    private List<TaskExecutor> taskExecutors;
+//    private Custom custom;
+//    private BusinessOpportunity businessOpportunity;
+//    private Order order;
+//    private Clue clue;
+//    private Contacts contacts;
+//    private List<TaskExecutor> taskExecutors;
     private List<TaskLog> taskLogs;
 
+    private String customName;
+    private String businessName;
+    private String orderName;
+    private String clueName;
+    private String contactsName;
+    private String contactsPhone;
+
+
+    private List<String> taskExecutors;
+
+
 }

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

@@ -0,0 +1,22 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.ActionLog;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.Clue;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-26
+ */
+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(Clue clue1);
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/BusinessItemCustomMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.BusinessItemCustom;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-02
+ */
+public interface BusinessItemCustomMapper extends BaseMapper<BusinessItemCustom> {
+
+}

+ 3 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/BusinessItemProductMapper.java

@@ -3,6 +3,8 @@ package com.management.platform.mapper;
 import com.management.platform.entity.BusinessItemProduct;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
+import java.util.List;
+
 /**
  * <p>
  *  Mapper 接口
@@ -13,4 +15,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface BusinessItemProductMapper extends BaseMapper<BusinessItemProduct> {
 
+    List<BusinessItemProduct> selectListToBoId(Integer id);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/BusinessProductMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.BusinessProduct;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-29
+ */
+public interface BusinessProductMapper extends BaseMapper<BusinessProduct> {
+
+}

+ 10 - 2
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/ClueMapper.java

@@ -3,6 +3,7 @@ package com.management.platform.mapper;
 import com.management.platform.entity.Clue;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 
 import java.util.List;
 
@@ -18,13 +19,20 @@ public interface ClueMapper extends BaseMapper<Clue> {
 
     List<Clue> list(Clue clue);
     List<Clue> list1(@Param("clue") Clue clue ,@Param("userId") String userId);
-    List<Clue> Deleterlist(Clue clue);
 
     Integer getTotal(Clue clue);
-    Integer getDeleterTotal(Clue clue);
 
     List<Clue> list2(@Param("clue") Clue clue ,@Param("userId") String userId);
 
     int getTotal1(@Param("clue") Clue clue ,@Param("userId") String userId);
     int getTotal2(@Param("clue") Clue clue ,@Param("userId") String userId);
+
+    @Select("select *," +
+            "(select `name` from sys_dict where code = 'ClueSources' and id =  clue_source_id) clueSourceValue," +
+            "(select `name` from sys_dict where code = 'CustomIndustry' and id =  customer_industry_id) customerIndustryValue," +
+            "(select `name` from sys_dict where code = 'CustomLevel' and id =  customer_level_id) customerLevelValue ," +
+            "(select `name` from user where id = incharger_id ) inchargerName," +
+            "(select `name` from user where id = create_id ) createName" +
+            " from clue where id = #{id}")
+    Clue selectById2Info(@Param("id") Integer id);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/ClueUploadfileMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.ClueUploadfile;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-25
+ */
+public interface ClueUploadfileMapper extends BaseMapper<ClueUploadfile> {
+
+}

+ 4 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/ContactsMapper.java

@@ -6,7 +6,9 @@ import com.management.platform.entity.Contacts;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.management.platform.entity.vo.ContactsVo;
 import com.management.platform.util.HttpRespMsg;
+import org.apache.ibatis.annotations.Select;
 
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -21,4 +23,6 @@ public interface ContactsMapper extends BaseMapper<Contacts> {
 
 
     Page<ContactsVo> pageContacts(Page page, Map<String, Object> map);
+
+    List<Contacts> selectListByIds(List<Integer> ids);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/CustomItemContactsMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.CustomItemContacts;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-02
+ */
+public interface CustomItemContactsMapper extends BaseMapper<CustomItemContacts> {
+
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/CustomMapper.java

@@ -1,8 +1,11 @@
 package com.management.platform.mapper;
 
+import com.management.platform.entity.Clue;
 import com.management.platform.entity.Custom;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
+import java.util.List;
+
 /**
  * <p>
  *  Mapper 接口
@@ -13,4 +16,17 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface CustomMapper extends BaseMapper<Custom> {
 
+    List<Custom> getList(Custom custom);
+
+    int getTotal(Custom custom);
+
+    List<Custom> getList1(Custom custom);
+
+    int getTotal1(Custom custom);
+
+    List<Custom> getList2(Custom custom);
+
+    int getTotal2(Custom custom);
+
+    Custom getInfo(Integer id);
 }

+ 6 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/OrderMapper.java

@@ -2,6 +2,10 @@ package com.management.platform.mapper;
 
 import com.management.platform.entity.Order;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.User;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
 
 /**
  * <p>
@@ -13,4 +17,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  */
 public interface OrderMapper extends BaseMapper<Order> {
 
+    @Select("select * from `order` WHERE company_id = #{companyId} AND is_delete = 0 ")
+    List<Order> getList(User user);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/OrderProductDetailMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.OrderProductDetail;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-03
+ */
+public interface OrderProductDetailMapper extends BaseMapper<OrderProductDetail> {
+
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/SeqMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.Seq;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-02
+ */
+public interface SeqMapper extends BaseMapper<Seq> {
+
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/StageMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.Stage;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-29
+ */
+public interface StageMapper extends BaseMapper<Stage> {
+
+}

+ 4 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/TaskMapper.java

@@ -5,11 +5,13 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.management.platform.entity.Clue;
 import com.management.platform.entity.Task;
 import com.management.platform.entity.TimeTask;
 import com.management.platform.entity.dto.TaskDto;
 import com.management.platform.entity.vo.TasKVo;
 import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
 
 import java.util.List;
@@ -62,4 +64,6 @@ public interface TaskMapper extends BaseMapper<Task> {
     List<TasKVo> getPageListTotalTask(TaskDto taskDto);
 
     void updateRepeatConfig(Task task);
+    @Select("select * , (select `name` from `user` where id = executor_id) executorName from task where clue_id = #{id} ORDER BY id DESC")
+    List<Task> selectByInfoList(Clue clue1);
 }

+ 23 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/UploadFileMapper.java

@@ -0,0 +1,23 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.Clue;
+import com.management.platform.entity.UploadFile;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-26
+ */
+public interface UploadFileMapper extends BaseMapper<UploadFile> {
+
+    @Select("select a.*,u.`name` userName from upload_file a left join `user` u on a.create_id = u.id where code = #{code} and item_id = #{id}")
+    List<UploadFile> selectByInfoList(@Param("code") String code ,@Param("id") Integer id);
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/ActionLogService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.ActionLog;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-26
+ */
+public interface ActionLogService extends IService<ActionLog> {
+
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/BusinessItemCustomService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.BusinessItemCustom;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-02
+ */
+public interface BusinessItemCustomService extends IService<BusinessItemCustom> {
+
+}

+ 22 - 3
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/BusinessOpportunityService.java

@@ -1,9 +1,12 @@
 package com.management.platform.service;
 
-import com.management.platform.entity.BusinessOpportunity;
+import com.management.platform.entity.*;
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.management.platform.entity.User;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -19,6 +22,8 @@ public interface BusinessOpportunityService extends IService<BusinessOpportunity
     List<BusinessOpportunity> getAll(BusinessOpportunity bo);
     List<BusinessOpportunity> getAll1(BusinessOpportunity bo, User user);
 
+    BusinessOpportunity getInfo(BusinessOpportunity bo ,User user);
+
     List<BusinessOpportunity> getAll2(BusinessOpportunity bo, User user);
 
     int getTotal(BusinessOpportunity bo);
@@ -28,5 +33,19 @@ public interface BusinessOpportunityService extends IService<BusinessOpportunity
 
     void insert(BusinessOpportunity bo);
 
-    void update(BusinessOpportunity bo);
+    void update(BusinessOpportunity bo,String userId);
+
+    void getAndTransfer(BusinessOpportunity bo, User user);
+
+    Object exportData(BusinessOpportunity bo, HttpServletRequest request) throws Exception;
+
+    HttpRespMsg saveProduct(BusinessOpportunity bo, User user);
+
+    Object uploadFile(BusinessItemCustom bo, HttpServletRequest request, MultipartFile file);
+
+    Object downFile(UploadFile file, HttpServletRequest request, HttpServletResponse response);
+
+    Object deleteFile(UploadFile file, HttpServletRequest request);
+
+    Object reFileName(UploadFile uploadFile, HttpServletRequest request);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/BusinessProductService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.BusinessProduct;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-29
+ */
+public interface BusinessProductService extends IService<BusinessProduct> {
+
+}

+ 14 - 2
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/ClueService.java

@@ -2,9 +2,13 @@ package com.management.platform.service;
 
 import com.management.platform.entity.Clue;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.management.platform.entity.UploadFile;
 import com.management.platform.entity.User;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -25,10 +29,8 @@ public interface ClueService extends IService<Clue> {
     List<Clue> getList(Clue clue);
     List<Clue> getList1(Clue clue, User user);
     List<Clue> getList2(Clue clue, User user);
-    List<Clue> getDeleterList(Clue clue);
 
     Integer getTotal(Clue clue);
-    Integer getDeleterTotal(Clue clue);
 
     Clue getInfo(Clue clue);
 
@@ -40,4 +42,14 @@ public interface ClueService extends IService<Clue> {
 
     int getTotal1(Clue clue, User user);
     int getTotal2(Clue clue, User user);
+
+    HttpRespMsg exportData(Clue clue, HttpServletRequest request) throws Exception;
+
+    Object uploadFile(Clue clue, HttpServletRequest request, MultipartFile file);
+
+    Object reFileName(UploadFile uploadFile, HttpServletRequest request);
+
+    Object deleteFile(UploadFile file, HttpServletRequest request);
+
+    Object downFile(UploadFile file, HttpServletRequest request, HttpServletResponse response);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/ClueUploadfileService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.ClueUploadfile;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-25
+ */
+public interface ClueUploadfileService extends IService<ClueUploadfile> {
+
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/CustomItemContactsService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.CustomItemContacts;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-02
+ */
+public interface CustomItemContactsService extends IService<CustomItemContacts> {
+
+}

+ 33 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/CustomService.java

@@ -2,6 +2,14 @@ package com.management.platform.service;
 
 import com.management.platform.entity.Custom;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.management.platform.entity.UploadFile;
+import com.management.platform.entity.User;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
 
 /**
  * <p>
@@ -13,4 +21,29 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface CustomService extends IService<Custom> {
 
+    HttpRespMsg insertAndUpdate(Custom custom, HttpServletRequest request);
+
+
+    void isDelete(List<Integer> ids);
+
+    void isRollback(List<Integer> ids);
+
+    void isReallyDelete(List<Integer> ids);
+
+    void getAndTransfer(Custom custom, User user);
+
+    HttpRespMsg getInfo(Custom custom, HttpServletRequest request);
+//    HttpRespMsg getLog(Custom custom, HttpServletRequest request);
+
+    HttpRespMsg getList(Custom custom, HttpServletRequest request);
+
+    HttpRespMsg getDeleteList(Custom custom, HttpServletRequest request);
+
+    Object uploadFile(Custom custom, HttpServletRequest request, MultipartFile file);
+
+    Object downFile(UploadFile file, HttpServletRequest request, HttpServletResponse response);
+
+    Object deleteFile(UploadFile file, HttpServletRequest request);
+
+    Object reFileName(UploadFile uploadFile, HttpServletRequest request);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/OrderProductDetailService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.OrderProductDetail;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-03
+ */
+public interface OrderProductDetailService extends IService<OrderProductDetail> {
+
+}

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

@@ -2,6 +2,7 @@ package com.management.platform.service;
 
 import com.management.platform.entity.Order;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.management.platform.util.HttpRespMsg;
 
 /**
  * <p>
@@ -13,4 +14,5 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface OrderService extends IService<Order> {
 
+    HttpRespMsg getList(String userId, String orderName,String orderCode, String productCode, Integer pageIndex, Integer pageSize,Integer isDelete);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/SeqService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.Seq;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-02
+ */
+public interface SeqService extends IService<Seq> {
+
+}

+ 22 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/StageService.java

@@ -0,0 +1,22 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.Stage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.management.platform.util.HttpRespMsg;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-29
+ */
+public interface StageService extends IService<Stage> {
+
+    HttpRespMsg changeStage(List<Stage> stages);
+
+    HttpRespMsg getStage();
+}

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

@@ -33,4 +33,6 @@ public interface TaskService extends IService<Task> {
     HttpRespMsg importData(MultipartFile multipartFile, HttpServletRequest request);
 
     HttpRespMsg exportData(TaskDto taskDto, HttpServletRequest request) throws Exception;
+
+    HttpRespMsg updateTaskStatus(TaskDto taskDto, HttpServletRequest request);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/UploadFileService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.UploadFile;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-26
+ */
+public interface UploadFileService extends IService<UploadFile> {
+
+}

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

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.ActionLog;
+import com.management.platform.mapper.ActionLogMapper;
+import com.management.platform.service.ActionLogService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-26
+ */
+@Service
+public class ActionLogServiceImpl extends ServiceImpl<ActionLogMapper, ActionLog> implements ActionLogService {
+
+}

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

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.BusinessItemCustom;
+import com.management.platform.mapper.BusinessItemCustomMapper;
+import com.management.platform.service.BusinessItemCustomService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-02
+ */
+@Service
+public class BusinessItemCustomServiceImpl extends ServiceImpl<BusinessItemCustomMapper, BusinessItemCustom> implements BusinessItemCustomService {
+
+}

+ 304 - 11
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/BusinessOpportunityServiceImpl.java

@@ -1,20 +1,41 @@
 package com.management.platform.service.impl;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
-import com.management.platform.entity.BusinessOpportunity;
-import com.management.platform.entity.User;
-import com.management.platform.mapper.BusinessOpportunityMapper;
+import com.management.platform.entity.*;
+import com.management.platform.mapper.*;
 import com.management.platform.service.BusinessOpportunityService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.management.platform.service.WxCorpInfoService;
+import com.management.platform.util.FileUtil;
+import com.management.platform.util.HttpRespMsg;
+import com.management.platform.util.MessageUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.net.URLEncoder;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.UUID;
 
 /**
  * <p>
- *  服务实现类
+ * 服务实现类
  * </p>
  *
  * @author Seyason
@@ -23,8 +44,25 @@ import java.util.List;
 @Service
 public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportunityMapper, BusinessOpportunity> implements BusinessOpportunityService {
 
+    @Resource
+    private ExcelExportServiceImpl excelExportService;
+    @Resource
+    private WxCorpInfoService wxCorpInfoService;
     @Resource
     private BusinessOpportunityMapper bOMapper;
+    @Resource
+    private TaskMapper taskMapper;
+    @Resource
+    private ActionLogMapper actionLogMapper;
+    @Resource
+    private UserMapper userMapper;
+    @Resource
+    private BusinessItemProductMapper biMapper;
+    @Autowired
+    private SysFormMapper sysFormMapper;
+    @Autowired
+    private UploadFileMapper uploadFileMapper;
+
     @Override
     public List<BusinessOpportunity> getAll(BusinessOpportunity bo) {
         return bOMapper.selectAllList(bo);
@@ -32,12 +70,39 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
 
     @Override
     public List<BusinessOpportunity> getAll1(BusinessOpportunity bo, User user) {
-        return bOMapper.selectAllList1(bo,user.getId());
+        return bOMapper.selectAllList1(bo, user.getId());
+    }
+
+    @Override
+    public BusinessOpportunity getInfo(BusinessOpportunity bo, User user) {
+        BusinessOpportunity businessOpportunity = bOMapper.selectById(bo.getId());
+        businessOpportunity.setActionLogList(actionLogMapper.selectList(new QueryWrapper<ActionLog>().eq("item_id", bo.getId()).eq("code", "business")));
+        businessOpportunity.setUploadFilePList(uploadFileMapper.selectByInfoList("business",bo.getId()));
+        businessOpportunity.setTaskList(taskMapper.selectList(new QueryWrapper<Task>().eq("business_opportunity_id",bo.getId())));
+        List<BusinessItemProduct> businessItemProducts = biMapper.selectListToBoId(bo.getId());
+        businessOpportunity.setBusinessItemProductList(businessItemProducts);
+        if (businessItemProducts.size() > 0){
+            BigDecimal finalPrice = new BigDecimal(0);
+            BigDecimal discountedPrice = new BigDecimal(0);
+            for (BusinessItemProduct businessItemProduct : businessItemProducts) {
+                BigDecimal price = businessItemProduct.getPrice();
+                // 原价
+                finalPrice = finalPrice.add(price.multiply(new BigDecimal(businessItemProduct.getQuantity())));
+                //折扣率
+                BigDecimal divide = new BigDecimal(businessItemProduct.getDiscount()).divide(new BigDecimal(100));
+                // 折后价格
+                discountedPrice = discountedPrice.add(price.multiply(divide));
+            }
+            BigDecimal divide = discountedPrice.divide(finalPrice);
+            // 整单折扣率
+            businessOpportunity.setFinalPrice(divide.multiply(new BigDecimal(100)));
+        }
+        return businessOpportunity;
     }
 
     @Override
     public List<BusinessOpportunity> getAll2(BusinessOpportunity bo, User user) {
-        return bOMapper.selectAllList2(bo,user.getId());
+        return bOMapper.selectAllList2(bo, user.getId());
     }
 
     @Override
@@ -47,24 +112,252 @@ public class BusinessOpportunityServiceImpl extends ServiceImpl<BusinessOpportun
 
     @Override
     public int getTotal1(BusinessOpportunity bo, User user) {
-        return bOMapper.getTotal1(bo,user.getId());
+        return bOMapper.getTotal1(bo, user.getId());
     }
 
     @Override
     public int getTotal2(BusinessOpportunity bo, User user) {
-        return bOMapper.getTotal2(bo,user.getId());
+        return bOMapper.getTotal2(bo, user.getId());
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void insert(BusinessOpportunity bo) {
+        setNull(bo);
         bo.setCreateTime(new Date());
         bOMapper.insert(bo);
+        ActionLog actionLog = new ActionLog();
+        actionLog.setUserId(bo.getUserId());
+        actionLog.setItemId(bo.getId());
+        actionLog.setCode("business");
+        actionLog.setName("创建了线索");
+        actionLogMapper.insert(actionLog);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void update(BusinessOpportunity bo, String userId) {
+        setNull(bo);
+        bOMapper.updateById(bo);
+        ActionLog log = new ActionLog();
+        log.setItemId(bo.getId());
+        log.setName("编辑了商机");
+        log.setCode("business");
+        log.setUserId(userId);
+        log.setCreatTime(new Date());
+        actionLogMapper.insert(log);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void getAndTransfer(BusinessOpportunity bo, User user) {
+        UpdateWrapper<BusinessOpportunity> updateWrapper = new UpdateWrapper<>();
+        String ids1 = bo.getIds();
+        List<Integer> ids = new ArrayList<>();
+        if (!ids1.isEmpty()) {
+            for (String id : ids1.split(",")) {
+                ids.add(Integer.parseInt(id));
+            }
+        }
+        updateWrapper.in("id", ids);
+        String inchargerId = bo.getInchargerId();
+        ActionLog clueLog = new ActionLog();
+        clueLog.setUserId(user.getId());
+        clueLog.setItemId(bo.getId());
+        clueLog.setCreatTime(new Date());
+        clueLog.setCode("business");
+
+        List<BusinessOpportunity> clues = bOMapper.selectList(new QueryWrapper<BusinessOpportunity>().in("id", ids));
+        for (BusinessOpportunity clue1 : clues) {
+            if (clue1.getInchargerId() == null) {
+                //认领
+                clueLog.setName("认领了线索");
+                clueLog.setUserId(user.getId());
+                bo.setInchargerId(user.getId());
+                actionLogMapper.insert(clueLog);
+            } else {
+                //转移
+                clueLog.setName("转移了线索");
+                bo.setInchargerId(bo.getInchargerId());
+                actionLogMapper.insert(clueLog);
+            }
+        }
+
+        updateWrapper.set("incharger_id", inchargerId);
+        bOMapper.update(null, updateWrapper);
+    }
+
+    @Value(value = "${upload.file}")
+    private String path;
+
+    @Override
+    public Object exportData(BusinessOpportunity bo, HttpServletRequest request) throws Exception {
+        User user = userMapper.selectById(request.getHeader("token"));
+        SysForm sysForm = sysFormMapper.selectOne(new LambdaQueryWrapper<SysForm>().eq(SysForm::getCompanyId, user.getCompanyId()).eq(SysForm::getCode, "Clue").eq(SysForm::getIsCurrent, 1));
+        WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, user.getCompanyId()));
+        String config = sysForm.getConfig();
+        JSONObject configOb = JSON.parseObject(config);
+        JSONArray configObJSONArray = configOb.getJSONArray("list");
+        List<List<String>> dataList = new ArrayList<>();
+        List<String> titleList = new ArrayList<>();
+        for (int i = 0; i < configObJSONArray.size(); i++) {
+            JSONObject item = configObJSONArray.getJSONObject(i);
+            titleList.add(item.getString("label"));
+        }
+        dataList.add(titleList);//设置表头
+
+
+        bo.setCompanyId(user.getCompanyId());
+
+        String fileName = "商机表导出_" + System.currentTimeMillis();
+        return excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo, fileName, dataList, path);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public HttpRespMsg saveProduct(BusinessOpportunity bo, User user) {
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.setMsg("操作成功");
+        biMapper.delete(new QueryWrapper<BusinessItemProduct>().eq("business_id",bo.getId()));
+        List<BusinessItemProduct> businessItemProductList = bo.getBusinessItemProductList();
+//        biMapper.saveBatch()
+        for (BusinessItemProduct businessItemProduct : businessItemProductList) {
+            biMapper.insert(businessItemProduct);
+        }
+        ActionLog al = new ActionLog();
+        al.setCode("business");
+        al.setName("编辑了产品");
+        al.setUserId(user.getId());
+        al.setItemId(bo.getId());
+        actionLogMapper.insert(al);
+        return msg;
+    }
+
+    @Value(value = "${upload.file}")
+    private String filePath;
+    @Override
+    public Object uploadFile(BusinessItemCustom bo, HttpServletRequest request, MultipartFile file) {
+        User user = userMapper.selectById(request.getHeader("token"));
+        if (!file.isEmpty()) { // 检查上传的文件是否为空
+            try {
+                // 获取上传文件的原始文件名
+                String originalFilename = file.getOriginalFilename();
+
+                // 创建文件存储目录
+                File uploadDir = new File(filePath);
+                if (!uploadDir.exists()) {
+                    uploadDir.mkdirs();
+
+                }
+                UploadFile uf = new UploadFile();
+                uf.setName(originalFilename);
+                String realName = "";
+                int pos = originalFilename.lastIndexOf(".");
+                String suffix = originalFilename.substring(pos).toLowerCase();
+                //用uuid替换原始的文件名
+                String purFName = UUID.randomUUID().toString().replaceAll("-", "");
+                realName = purFName + suffix;
+
+
+                uf.setPath(filePath + realName);
+                uf.setCode("business");
+                uf.setItemId(bo.getId());
+                uf.setRealName(realName);
+                uf.setCreateTime(new Date());
+                uf.setCreateId(user.getId());
+                uploadFileMapper.insert(uf);
+                // 构建上传文件的目标路径
+                String filePath1 = filePath + realName;
+
+                // 在服务器上创建文件
+                File dest = new File(filePath1);
+
+                // 将上传的文件保存到目标路径
+                file.transferTo(dest);
+
+                // 文件上传成功的响应消息
+                HttpRespMsg msg = new HttpRespMsg();
+                msg.setMsg("上传成功");
+                return msg;
+            } catch (IOException e) {
+                e.printStackTrace();
+                // 文件上传失败的响应消息
+                HttpRespMsg msg = new HttpRespMsg();
+                msg.setError("上传成功失败");
+                return msg;
+            }
+        } else {
+            // 文件为空的响应消息
+            HttpRespMsg msg = new HttpRespMsg();
+            msg.setError("请选择上传文件");
+            return msg;
+        }    }
+
+    @Override
+    public Object downFile(UploadFile file, HttpServletRequest request, HttpServletResponse response) {
+        HttpRespMsg msg = new HttpRespMsg();
+        try {
+            ServletOutputStream os = response.getOutputStream();
+            UploadFile uploadFile = uploadFileMapper.selectById(file.getId());
+            if (uploadFile == null ){
+                msg.setError("文件未找到");
+                return msg;
+            }
+
+            File uploadFile1 = new File(uploadFile.getPath());
+            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(uploadFile.getName(), "UTF-8"));
+            response.setContentType("application/octet-stream");
+            // 读取文件的字节流
+            os.write(FileUtil.readFileByBytes(uploadFile1));
+            os.flush();
+
+        } catch (IOException e) {
+            msg.setError(MessageUtils.message("file.error"));
+            e.printStackTrace();
+        }
+        return msg;
     }
 
     @Override
-    public void update(BusinessOpportunity bo) {
-        UpdateWrapper<Object> update = new UpdateWrapper<>();
+    public Object deleteFile(UploadFile file, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        try {
+            UploadFile uploadFile = uploadFileMapper.selectById(file.getId());
+            uploadFileMapper.deleteById(uploadFile.getId());
+            String realName = uploadFile.getRealName();
+            File file1 = new File(path + realName);
+            file1.delete();
+            msg.setMsg("删除成功");
+        } catch (Exception e) {
+            e.printStackTrace();
+            msg.setError("删除失败");
+        }
+        return msg;
+    }
+
+    @Override
+    public Object reFileName(UploadFile uploadFile, HttpServletRequest request) {
+        return uploadFileMapper.update(null, new UpdateWrapper<UploadFile>().eq("id", uploadFile.getId()).set("name", uploadFile.getName()));
+    }
 
-//        bOMapper.update(bo);
+    private BusinessOpportunity setNull(BusinessOpportunity bo) {
+        if (bo.getPlate1() == "") {
+            bo.setPlate1(null);
+        }
+        if (bo.getPlate2() == "") {
+            bo.setPlate2(null);
+        }
+        if (bo.getPlate3() == "") {
+            bo.setPlate3(null);
+        }
+        if (bo.getPlate4() == "") {
+            bo.setPlate4(null);
+        }
+        if (bo.getPlate5() == "") {
+            bo.setPlate5(null);
+        }
+        return bo;
     }
+
+
 }

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

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.BusinessProduct;
+import com.management.platform.mapper.BusinessProductMapper;
+import com.management.platform.service.BusinessProductService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-29
+ */
+@Service
+public class BusinessProductServiceImpl extends ServiceImpl<BusinessProductMapper, BusinessProduct> implements BusinessProductService {
+
+}

+ 257 - 49
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ClueServiceImpl.java

@@ -1,24 +1,40 @@
 package com.management.platform.service.impl;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
-import com.management.platform.entity.Clue;
-import com.management.platform.entity.ClueLog;
-import com.management.platform.entity.User;
-import com.management.platform.mapper.ClueLogMapper;
-import com.management.platform.mapper.ClueMapper;
+import com.management.platform.entity.*;
+import com.management.platform.entity.vo.TasKVo;
+import com.management.platform.mapper.*;
 import com.management.platform.service.ClueService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.management.platform.service.SysFunctionService;
 import com.management.platform.service.UserService;
+import com.management.platform.service.WxCorpInfoService;
+import com.management.platform.util.FileUtil;
+import com.management.platform.util.HttpRespMsg;
+import com.management.platform.util.MessageUtils;
+import org.apache.poi.ss.formula.functions.T;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
 
+import javax.annotation.Resource;
+import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import java.beans.Transient;
-import java.util.Date;
-import java.util.List;
+import java.io.File;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
 
 /**
  * <p>
@@ -36,9 +52,26 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
     @Autowired
     private ClueMapper clueMapper;
     @Autowired
+    private TaskMapper taskMapper;
+    @Autowired
+    private ClueUploadfileMapper clueUploadfileMapper;
+    @Resource
+    private WxCorpInfoService wxCorpInfoService;
+    @Autowired
     private ClueLogMapper clueLogMapper;
     @Autowired
+    private UploadFileMapper uploadFileMapper;
+    @Autowired
+    private SysFormMapper sysFormMapper;
+    @Autowired
+    private UserMapper userMapper;
+    @Autowired
     private UserService userService;
+    @Autowired
+    private ActionLogMapper actionLogMapper;
+    @Resource
+    private ExcelExportServiceImpl excelExportService;
+
 
     @Override
     @Transactional(rollbackFor = Exception.class)
@@ -46,13 +79,20 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
         setNull(clue);
         clue.setCreateTime(new Date());
         clueMapper.insert(clue);
-        Integer id = clue.getId();
-        ClueLog clueLog = new ClueLog();
-        clueLog.setClueId(id);
-        clueLog.setName("创建了线索");
+//        Integer id = clue.getId();
+//        ClueLog clueLog = new ClueLog();
+//        clueLog.setClueId(id);
+//        clueLog.setName("创建了线索");
 //        clueLog.setUserId(clue.getCreateId());
-        clueLog.setCreatTime(new Date());
-        clueLogMapper.insert(clueLog);
+//        clueLog.setCreatTime(new Date());
+//        clueLogMapper.insert(clueLog);
+        ActionLog log = new ActionLog();
+        log.setItemId(clue.getId());
+        log.setName("创建了线索");
+        log.setCode("clue");
+        log.setUserId(clue.getCreateId());
+        log.setCreatTime(new Date());
+        actionLogMapper.insert(log);
     }
 
     @Override
@@ -60,12 +100,13 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
     public void update(Clue clue) {
         setNull(clue);
         clueMapper.updateById(clue);
-        ClueLog clueLog = new ClueLog();
-        clueLog.setClueId(clue.getId());
-        clueLog.setName("编辑了线索");
-//        clueLog.setUserId(clue.getCreateId());
-        clueLog.setCreatTime(new Date());
-        clueLogMapper.insert(clueLog);
+        ActionLog log = new ActionLog();
+        log.setItemId(clue.getId());
+        log.setName("编辑了线索");
+        log.setCode("clue");
+        log.setUserId(clue.getCreateId());
+        log.setCreatTime(new Date());
+        actionLogMapper.insert(log);
     }
 
     private Clue setNull(Clue clue) {
@@ -97,6 +138,9 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
         clueMapper.update(clue, updateWrapper);
     }
 
+    @Value(value = "${upload.file}")
+    private String path;
+
     @Override
     public List<Clue> getList(Clue clue) {
         return clueMapper.list(clue);
@@ -112,28 +156,35 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
         return clueMapper.list2(clue, user.getId());
     }
 
-    @Override
-    public List<Clue> getDeleterList(Clue clue) {
-        return clueMapper.Deleterlist(clue);
-    }
 
     @Override
     public Integer getTotal(Clue clue) {
         return clueMapper.getTotal(clue);
     }
 
-    @Override
-    public Integer getDeleterTotal(Clue clue) {
-        return clueMapper.getDeleterTotal(clue);
-    }
 
     @Override
     public Clue getInfo(Clue clue) {
-        Clue clue1 = clueMapper.selectById(clue.getId());
-        QueryWrapper<ClueLog> queryWrapper = new QueryWrapper<>();
-        queryWrapper.eq("clue_id", clue.getId());
-        List<ClueLog> logs = clueLogMapper.selectList(queryWrapper);
-        clue1.setClueLogList(logs);
+        Clue clue1 = clueMapper.selectById2Info(clue.getId());
+        clue1.setClueLogList(actionLogMapper.selectByInfoList(clue1));
+        clue1.setFiles(uploadFileMapper.selectByInfoList("clue", clue1.getId()));
+        List<Task> tasks = taskMapper.selectList(new QueryWrapper<Task>().in("clue_id", clue.getId()));
+        for (Task task : tasks) {
+            String executorId = task.getExecutorId();
+            List<String> ids1 = new ArrayList<>();
+            List<String> userNames = new ArrayList<>();
+            if (!executorId.isEmpty()) {
+                for (String id : executorId.split(",")) {
+                    ids1.add(id);
+                }
+                List<User> users = userMapper.selectList(new QueryWrapper<User>().in("id", ids1));
+                for (User user : users) {
+                    userNames.add(user.getName());
+                }
+                task.setExecutorNames(userNames);
+            }
+            clue1.setTaskList(tasks);
+        }
         return clue1;
     }
 
@@ -154,38 +205,195 @@ public class ClueServiceImpl extends ServiceImpl<ClueMapper, Clue> implements Cl
     }
 
     @Override
-    public void getAndTransfer(Clue clue,User user) {
+    public void getAndTransfer(Clue clue, User user) {
         UpdateWrapper<Clue> updateWrapper = new UpdateWrapper<>();
-        updateWrapper.eq("id",clue.getId());
+        String ids1 = clue.getIds();
+        List<Integer> ids = new ArrayList<>();
+        if (!ids1.isEmpty()) {
+            for (String id : ids1.split(",")) {
+                ids.add(Integer.parseInt(id));
+            }
+        }
+        updateWrapper.in("id", ids);
         String inchargerId = clue.getInchargerId();
-        ClueLog clueLog = new ClueLog();
+        ActionLog clueLog = new ActionLog();
         clueLog.setUserId(user.getId());
-        clueLog.setClueId(clue.getId());
         clueLog.setCreatTime(new Date());
-        if (inchargerId == null ){
-            //认领
-            clueLog.setName("认领了线索");
-            clue.setInchargerId(user.getId());
-            clueLogMapper.insert(clueLog);
-        }else {
-            //转移
-            clueLog.setName("转移了线索");
-            clue.setInchargerId(clue.getInchargerId());
-            clueLogMapper.insert(clueLog);
+        clueLog.setCode("clue");
+
+        List<Clue> clues = clueMapper.selectList(new QueryWrapper<Clue>().in("id", ids));
+        for (Clue clue1 : clues) {
+            clueLog.setItemId(clue1.getId());
+            if (clue1.getInchargerId() == null) {
+                //认领
+                clueLog.setName("认领了线索");
+                clueLog.setUserId(user.getId());
+                clue.setInchargerId(user.getId());
+                actionLogMapper.insert(clueLog);
+            } else {
+                //转移
+                clueLog.setName("转移了线索");
+                clue.setInchargerId(clue.getInchargerId());
+                actionLogMapper.insert(clueLog);
+            }
         }
-        clueMapper.update(clue, updateWrapper);
+
+        updateWrapper.set("incharger_id", inchargerId);
+        clueMapper.update(null, updateWrapper);
 
     }
 
     @Override
     public int getTotal1(Clue clue, User user) {
-        return clueMapper.getTotal1(clue,user.getId());
+        return clueMapper.getTotal1(clue, user.getId());
     }
 
     @Override
     public int getTotal2(Clue clue, User user) {
-        return clueMapper.getTotal2(clue,user.getId());
+        return clueMapper.getTotal2(clue, user.getId());
+
+    }
+
+
+    @Override
+    public HttpRespMsg exportData(Clue clue, HttpServletRequest request) throws Exception {
+        User user = userMapper.selectById(request.getHeader("token"));
+        SysForm sysForm = sysFormMapper.selectOne(new LambdaQueryWrapper<SysForm>().eq(SysForm::getCompanyId, user.getCompanyId()).eq(SysForm::getCode, "Clue").eq(SysForm::getIsCurrent, 1));
+        WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, user.getCompanyId()));
+        String config = sysForm.getConfig();
+        JSONObject configOb = JSON.parseObject(config);
+        JSONArray configObJSONArray = configOb.getJSONArray("list");
+        List<List<String>> dataList = new ArrayList<>();
+        List<String> titleList = new ArrayList<>();
+        for (int i = 0; i < configObJSONArray.size(); i++) {
+            JSONObject item = configObJSONArray.getJSONObject(i);
+            titleList.add(item.getString("label"));
+        }
+        dataList.add(titleList);//设置表头
+
+
+        clue.setCompanyId(user.getCompanyId());
+
+        String fileName = "线索表导出_" + System.currentTimeMillis();
+        return excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo, fileName, dataList, path);
+    }
+
+    @Value(value = "${upload.file}")
+    private String filePath;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Object uploadFile(Clue clue, HttpServletRequest request, MultipartFile file) {
+        User user = userMapper.selectById(request.getHeader("token"));
+        if (!file.isEmpty()) { // 检查上传的文件是否为空
+            try {
+                // 获取上传文件的原始文件名
+                String originalFilename = file.getOriginalFilename();
+
+                // 创建文件存储目录
+                File uploadDir = new File(filePath);
+                if (!uploadDir.exists()) {
+                    uploadDir.mkdirs();
+
+                }
+                UploadFile uf = new UploadFile();
+                uf.setName(originalFilename);
+                String realName = "";
+                int pos = originalFilename.lastIndexOf(".");
+                String suffix = originalFilename.substring(pos).toLowerCase();
+                //用uuid替换原始的文件名
+                String purFName = UUID.randomUUID().toString().replaceAll("-", "");
+                realName = purFName + suffix;
+
+                long size = file.getSize();
+                String s = "MB";
+                double  l = size / 1024.00 / 1024.00;
+                System.out.println(size);
+                uf.setPath("/file/" + realName);
+                uf.setCode("clue");
+                uf.setSize(l+s);
+                uf.setItemId(clue.getId());
+                uf.setRealName(realName);
+                uf.setCreateTime(new Date());
+                uf.setCreateId(user.getId());
+                uploadFileMapper.insert(uf);
+                // 构建上传文件的目标路径
+                String filePath1 = filePath + realName;
+
+                // 在服务器上创建文件
+                File dest = new File(filePath1);
 
+                // 将上传的文件保存到目标路径
+                file.transferTo(dest);
+
+                // 文件上传成功的响应消息
+                HttpRespMsg msg = new HttpRespMsg();
+                msg.setMsg("上传成功");
+                return msg;
+            } catch (IOException e) {
+                e.printStackTrace();
+                // 文件上传失败的响应消息
+                HttpRespMsg msg = new HttpRespMsg();
+                msg.setError("上传成功失败");
+                return msg;
+            }
+        } else {
+            // 文件为空的响应消息
+            HttpRespMsg msg = new HttpRespMsg();
+            msg.setError("请选择上传文件");
+            return msg;
+        }
+    }
+
+    @Override
+    public Object reFileName(UploadFile uploadFile, HttpServletRequest request) {
+        return uploadFileMapper.update(null, new UpdateWrapper<UploadFile>().eq("id", uploadFile.getId()).set("name", uploadFile.getName()));
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Object deleteFile(UploadFile file, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        try {
+            UploadFile uploadFile = uploadFileMapper.selectById(file.getId());
+            uploadFileMapper.deleteById(uploadFile.getId());
+            String realName = uploadFile.getRealName();
+            File file1 = new File(path + realName);
+            file1.delete();
+            msg.setMsg("删除成功");
+        } catch (Exception e) {
+            e.printStackTrace();
+            msg.setError("删除失败");
+        }
+        return msg;
+    }
+
+    @Override
+    public Object downFile(UploadFile file, HttpServletRequest request, HttpServletResponse response) {
+        HttpRespMsg msg = new HttpRespMsg();
+//        try {
+//            ServletOutputStream os = response.getOutputStream();
+            UploadFile uploadFile = uploadFileMapper.selectById(file.getId());
+        String path1 = uploadFile.getPath();
+        path1 = path1.substring(2);
+        msg.setData(path1);
+//            if (uploadFile == null ){
+//                msg.setError("文件未找到");
+//                return msg;
+//            }
+//
+//            File uploadFile1 = new File(uploadFile.getPath());
+//            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(uploadFile.getName(), "UTF-8"));
+//            response.setContentType("application/octet-stream");
+//            // 读取文件的字节流
+//            os.write(FileUtil.readFileByBytes(uploadFile1));
+//            os.flush();
+//
+//        } catch (IOException e) {
+//            msg.setError(MessageUtils.message("file.error"));
+//            e.printStackTrace();
+//        }
+        return msg;
     }
 
 

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

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.ClueUploadfile;
+import com.management.platform.mapper.ClueUploadfileMapper;
+import com.management.platform.service.ClueUploadfileService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-03-25
+ */
+@Service
+public class ClueUploadfileServiceImpl extends ServiceImpl<ClueUploadfileMapper, ClueUploadfile> implements ClueUploadfileService {
+
+}

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

@@ -194,7 +194,7 @@ public class ContactsServiceImpl extends ServiceImpl<ContactsMapper, Contacts> i
         UpdateWrapper<Contacts> contactsUpdateWrapper = new UpdateWrapper<>();
         List<BusinessOpportunity> opportunityList = businessOpportunityMapper.selectList(new QueryWrapper<BusinessOpportunity>().in("contacts_id", ids));
         if (!opportunityList.isEmpty()){
-            List<BusinessOpportunity> collect = opportunityList.stream().filter(o -> o.getStage() < 4).collect(Collectors.toList());
+            List<BusinessOpportunity> collect = opportunityList.stream().filter(o -> o.getStageId()!=null&&o.getStageId() < 5).collect(Collectors.toList());
             if (!collect.isEmpty()){
                 String oName=" ";
                 for (BusinessOpportunity businessOpportunity : collect) {
@@ -205,7 +205,7 @@ public class ContactsServiceImpl extends ServiceImpl<ContactsMapper, Contacts> i
         }
         List<Task> taskList = taskMapper.selectList(new QueryWrapper<Task>().in("contacts_id", ids));
         if (!taskList.isEmpty()){
-            List<Task> collect = taskList.stream().filter(t -> t.getStatus() != 2).collect(Collectors.toList());
+            List<Task> collect = taskList.stream().filter(t ->t.getStatus()!=null&&t.getStatus() != 2).collect(Collectors.toList());
             if (!collect.isEmpty()){
                 msg.setError("存在任务未完成且跟联系人有关");
             }

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

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.CustomItemContacts;
+import com.management.platform.mapper.CustomItemContactsMapper;
+import com.management.platform.service.CustomItemContactsService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-02
+ */
+@Service
+public class CustomItemContactsServiceImpl extends ServiceImpl<CustomItemContactsMapper, CustomItemContacts> implements CustomItemContactsService {
+
+}

+ 378 - 3
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/CustomServiceImpl.java

@@ -1,14 +1,32 @@
 package com.management.platform.service.impl;
 
-import com.management.platform.entity.Custom;
-import com.management.platform.mapper.CustomMapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.management.platform.entity.*;
+import com.management.platform.mapper.*;
 import com.management.platform.service.CustomService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.management.platform.service.SysFunctionService;
+import com.management.platform.util.FileUtil;
+import com.management.platform.util.HttpRespMsg;
+import com.management.platform.util.MessageUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.util.*;
 
 /**
  * <p>
- *  服务实现类
+ * 服务实现类
  * </p>
  *
  * @author Seyason
@@ -16,5 +34,362 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom> implements CustomService {
+    @Autowired
+    private UserMapper userMapper;
+    @Autowired
+    private CustomMapper customMapper;
+    @Autowired
+    private BusinessItemCustomMapper businessItemCustomMapper;
+    @Autowired
+    private CustomItemContactsMapper customItemContactsMapper;
+    @Autowired
+    private ActionLogMapper actionLogMapper;
+
+    @Autowired
+    private UploadFileMapper uploadFileMapper;
+
+    @Autowired
+    private BusinessOpportunityMapper businessOpportunityMapper;
+    @Autowired
+    private SysFunctionService sysFunctionService;
+
+    @Autowired
+    private ContactsMapper contactsMapper;
+
+    @Override
+    public HttpRespMsg insertAndUpdate(Custom custom, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        if (custom.getCustomName().isEmpty()) {
+            msg.setError("请填写客户名称");
+            return msg;
+        }
+        User user = userMapper.selectById(request.getHeader("Token"));
+        custom.setCompanyId(user.getCompanyId());
+        setNull(custom);
+        if (custom.getId() != null) {
+            Custom custom1 = customMapper.selectById(custom.getId());
+            if (customMapper.selectCount(new QueryWrapper<Custom>()
+                    .eq("custom_name", custom.getCustomName())
+                    .ne("custom_name", custom1.getCustomName())) > 0) {
+                msg.setError("客户名称重复了");
+                return msg;
+            }
+            if (customMapper.selectCount(new QueryWrapper<Custom>()
+                    .eq("tel_phone", custom.getTelPhone())
+                    .ne("tel_phone", custom1.getTelPhone())
+            ) > 0) {
+                msg.setError("电话号码重复了");
+                return msg;
+            }
+            ActionLog actionLog = new ActionLog();
+            actionLog.setCode("custom");
+            actionLog.setCreatTime(new Date());
+            actionLog.setName("创建了客户");
+            actionLog.setItemId(custom.getId());
+            actionLog.setUserId(user.getId());
+            actionLogMapper.insert(actionLog);
+            customMapper.updateById(custom);
+        } else {
+            if (customMapper.selectCount(new QueryWrapper<Custom>().eq("custom_name", custom.getCustomName())) > 0) {
+                msg.setError("客户名称重复了");
+                return msg;
+            }
+            if (customMapper.selectCount(new QueryWrapper<Custom>().eq("tel_phone", custom.getTelPhone())) > 0) {
+                msg.setError("电话号码重复了");
+                return msg;
+            }
+            custom.setCreateTime(new Date());
+            custom.setCreatorId(user.getId());
+            ActionLog actionLog = new ActionLog();
+            actionLog.setCode("custom");
+            actionLog.setCreatTime(new Date());
+            actionLog.setName("编辑了客户");
+            actionLog.setUserId(user.getId());
+            actionLog.setItemId(custom.getId());
+            actionLogMapper.insert(actionLog);
+            customMapper.insert(custom);
+        }
+        msg.setMsg("操作成功");
+        return msg;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void isDelete(List<Integer> ids) {
+        UpdateWrapper<Custom> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.in("id", ids);
+        Custom custom = new Custom();
+        custom.setIsDelete(1);
+        customMapper.update(custom, updateWrapper);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void isRollback(List<Integer> ids) {
+        UpdateWrapper<Custom> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.in("id", ids);
+        Custom custom = new Custom();
+        custom.setIsDelete(0);
+        customMapper.update(custom, updateWrapper);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void isReallyDelete(List<Integer> ids) {
+        customMapper.deleteBatchIds(ids);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void getAndTransfer(Custom custom, User user) {
+        UpdateWrapper<Custom> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.eq("id", custom.getId());
+        Custom custom1 = customMapper.selectById(custom.getId());
+        String inchargerId = custom1.getInchargerId();
+        if (inchargerId == null) {
+            //认领
+            ActionLog actionLog = new ActionLog();
+            actionLog.setCode("custom");
+            actionLog.setCreatTime(new Date());
+            actionLog.setName("认领了客户");
+            actionLog.setUserId(user.getId());
+            actionLog.setItemId(custom.getId());
+            actionLogMapper.insert(actionLog);
+        } else {
+            //转移
+            ActionLog actionLog = new ActionLog();
+            actionLog.setCode("custom");
+            actionLog.setCreatTime(new Date());
+            actionLog.setName("转移了客户");
+            actionLog.setUserId(user.getId());
+            actionLog.setItemId(custom.getId());
+            actionLogMapper.insert(actionLog);
+        }
+        customMapper.update(custom, updateWrapper);
+    }
+
+    @Override
+    public HttpRespMsg getInfo(Custom custom, HttpServletRequest request) {
+        Custom custom1 = customMapper.getInfo(custom.getId());
+
+        // 附件列表
+        custom1.setFiles(uploadFileMapper.selectList(new QueryWrapper<UploadFile>().eq("code", "custom").eq("item_id",custom1.getId())));
+        //商机列表
+        custom1.setBusinessOpportunitys(businessOpportunityMapper.selectList(new QueryWrapper<BusinessOpportunity>().eq("customer_id",custom1.getId())));
+        //操作记录
+        custom1.setActionLogs(actionLogMapper.selectList(new QueryWrapper<ActionLog>().eq("code","custom").eq("item_id",custom1.getId())));
+        List<CustomItemContacts> contacts = customItemContactsMapper.selectList(new QueryWrapper<CustomItemContacts>().eq("contacts_id", custom1.getId()));
+        List<Integer> ids = new ArrayList<>();
+        for (CustomItemContacts contact : contacts) {
+            ids.add(contact.getCustomId());
+        }
+//        List<Contacts> cs = contactsMapper.selectList(new QueryWrapper<Contacts>().in("id", ids));
+        List<Contacts> cs = contactsMapper.selectListByIds(ids);
+        custom1.setContactsList(cs);
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        httpRespMsg.setData(custom1);
+        return httpRespMsg;
+    }
+
+//    @Override
+//    public HttpRespMsg getLog(Custom custom, HttpServletRequest request) {
+//        List<ActionLog> actionLogs = actionLogMapper.selectList(new QueryWrapper<ActionLog>().eq("code", "custom").eq("item_id", custom.getId()));
+//        HttpRespMsg httpRespMsg = new HttpRespMsg();
+//        httpRespMsg.setData(actionLogs);
+//        return httpRespMsg;
+//    }
+
+    @Override
+    public HttpRespMsg getList(Custom custom, HttpServletRequest request) {
+        User user = userMapper.selectById(request.getHeader("Token"));
+        custom.setCompanyId(user.getCompanyId());
+        custom.setIsDelete(0);
+        custom.setUserId(user.getId());
+        custom.setEndTime(custom.getEndTime() + " 23:59:59");
+        custom.setPageIndex((custom.getPageIndex()-1) * custom.getPageFrom() );
+        boolean isAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部客户");
+        boolean isNotAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看负责部门客户");
+        List<Custom> list = new ArrayList<>();
+        int i = 0;
+        if (!isAll) {
+            //查看全部线索
+            list = customMapper.getList(custom);
+            i = customMapper.getTotal(custom);
+        } else if (!isNotAll) {
+            //查看负责部门线索 找出所处部门下所有的负责人
+            list = customMapper.getList1(custom);
+            i = customMapper.getTotal1(custom);
+        } else {
+            // 查看负责人为 自己 和 null的数据
+            list = customMapper.getList2(custom);
+            i = customMapper.getTotal2(custom);
+        }
+        HashMap<Object, Object> map = new HashMap<>();
+        map.put("data", list);
+        map.put("total", i);
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.setData(map);
+        return msg;
+    }
+
+    @Override
+    public HttpRespMsg getDeleteList(Custom custom, HttpServletRequest request) {
+        User user = userMapper.selectById(request.getHeader("Token"));
+        custom.setCompanyId(user.getCompanyId());
+        custom.setIsDelete(1);
+        custom.setUserId(user.getId());
+        custom.setEndTime(custom.getEndTime() + " 23:59:59");
+        custom.setPageIndex((custom.getPageIndex()-1) * custom.getPageFrom() );
+        boolean isAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部客户");
+        boolean isNotAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看负责部门客户");
+        List<Custom> list = new ArrayList<>();
+        int i = 0;
+        if (!isAll) {
+            //查看全部线索
+            list = customMapper.getList(custom);
+            i = customMapper.getTotal(custom);
+        } else if (!isNotAll) {
+            //查看负责部门线索 找出所处部门下所有的负责人
+            list = customMapper.getList1(custom);
+            i = customMapper.getTotal1(custom);
+        } else {
+            // 查看负责人为 自己 和 null的数据
+            list = customMapper.getList2(custom);
+            i = customMapper.getTotal2(custom);
+        }
+        HashMap<Object, Object> map = new HashMap<>();
+        map.put("data", list);
+        map.put("total", i);
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.setData(map);
+        return msg;
+    }
+
+
+    @Value(value = "${upload.file}")
+    private String filePath;
+    @Override
+    public Object uploadFile(Custom custom, HttpServletRequest request, MultipartFile file) {
+        User user = userMapper.selectById(request.getHeader("token"));
+        if (!file.isEmpty()) { // 检查上传的文件是否为空
+            try {
+                // 获取上传文件的原始文件名
+                String originalFilename = file.getOriginalFilename();
+
+                // 创建文件存储目录
+                File uploadDir = new File(filePath);
+                if (!uploadDir.exists()) {
+                    uploadDir.mkdirs();
+
+                }
+                UploadFile uf = new UploadFile();
+                uf.setName(originalFilename);
+                String realName = "";
+                int pos = originalFilename.lastIndexOf(".");
+                String suffix = originalFilename.substring(pos).toLowerCase();
+                //用uuid替换原始的文件名
+                String purFName = UUID.randomUUID().toString().replaceAll("-", "");
+                realName = purFName + suffix;
+
+
+                uf.setPath(filePath + realName);
+                uf.setCode("custom");
+                uf.setItemId(custom.getId());
+                uf.setRealName(realName);
+                uf.setCreateTime(new Date());
+                uf.setCreateId(user.getId());
+                uploadFileMapper.insert(uf);
+                // 构建上传文件的目标路径
+                String filePath1 = filePath + realName;
+
+                // 在服务器上创建文件
+                File dest = new File(filePath1);
+
+                // 将上传的文件保存到目标路径
+                file.transferTo(dest);
+
+                // 文件上传成功的响应消息
+                HttpRespMsg msg = new HttpRespMsg();
+                msg.setMsg("上传成功");
+                return msg;
+            } catch (IOException e) {
+                e.printStackTrace();
+                // 文件上传失败的响应消息
+                HttpRespMsg msg = new HttpRespMsg();
+                msg.setError("上传成功失败");
+                return msg;
+            }
+        } else {
+            // 文件为空的响应消息
+            HttpRespMsg msg = new HttpRespMsg();
+            msg.setError("请选择上传文件");
+            return msg;
+        }
+    }
+
+    @Override
+    public Object downFile(UploadFile file, HttpServletRequest request, HttpServletResponse response) {
+        HttpRespMsg msg = new HttpRespMsg();
+        try {
+            ServletOutputStream os = response.getOutputStream();
+            UploadFile uploadFile = uploadFileMapper.selectById(file.getId());
+            if (uploadFile == null ){
+                msg.setError("文件未找到");
+                return msg;
+            }
+
+            File uploadFile1 = new File(uploadFile.getPath());
+            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(uploadFile.getName(), "UTF-8"));
+            response.setContentType("application/octet-stream");
+            // 读取文件的字节流
+            os.write(FileUtil.readFileByBytes(uploadFile1));
+            os.flush();
+
+        } catch (IOException e) {
+            msg.setError(MessageUtils.message("file.error"));
+            e.printStackTrace();
+        }
+        return msg;    }
+
+    @Override
+    public Object deleteFile(UploadFile file, HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        try {
+            UploadFile uploadFile = uploadFileMapper.selectById(file.getId());
+            uploadFileMapper.deleteById(uploadFile.getId());
+            String realName = uploadFile.getRealName();
+            File file1 = new File(uploadFile.getPath());
+            file1.delete();
+            msg.setMsg("删除成功");
+        } catch (Exception e) {
+            e.printStackTrace();
+            msg.setError("删除失败");
+        }
+        return msg;    }
+
+    @Override
+    public Object reFileName(UploadFile uploadFile, HttpServletRequest request) {
+        return uploadFileMapper.update(null, new UpdateWrapper<UploadFile>().eq("id", uploadFile.getId()).set("name", uploadFile.getName()));
+    }
+
+
+    private Custom setNull(Custom clue) {
+        if (clue.getPlate1() == "") {
+            clue.setPlate1(null);
+        }
+        if (clue.getPlate2() == "") {
+            clue.setPlate2(null);
+        }
+        if (clue.getPlate3() == "") {
+            clue.setPlate3(null);
+        }
+        if (clue.getPlate4() == "") {
+            clue.setPlate4(null);
+        }
+        if (clue.getPlate5() == "") {
+            clue.setPlate5(null);
+        }
+        return clue;
+    }
 
 }

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

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.OrderProductDetail;
+import com.management.platform.mapper.OrderProductDetailMapper;
+import com.management.platform.service.OrderProductDetailService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2024-04-03
+ */
+@Service
+public class OrderProductDetailServiceImpl extends ServiceImpl<OrderProductDetailMapper, OrderProductDetail> implements OrderProductDetailService {
+
+}

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

@@ -1,10 +1,22 @@
 package com.management.platform.service.impl;
 
-import com.management.platform.entity.Order;
-import com.management.platform.mapper.OrderMapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.management.platform.entity.*;
+import com.management.platform.mapper.*;
+import com.management.platform.service.DepartmentService;
 import com.management.platform.service.OrderService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.management.platform.service.SysFunctionService;
+import com.management.platform.util.HttpRespMsg;
 import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -17,4 +29,113 @@ import org.springframework.stereotype.Service;
 @Service
 public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
 
+    @Resource
+    private OrderMapper orderMapper;
+    @Resource
+    private HttpServletRequest request;
+    @Resource
+    private UserMapper userMapper;
+    @Resource
+    private SysFunctionService sysFunctionService;
+    @Resource
+    private DepartmentMapper departmentMapper;
+    @Resource
+    private DepartmentOtherManagerMapper departmentOtherManagerMapper;
+    @Resource
+    private SysDictMapper sysDictMapper;
+
+    @Override
+    public HttpRespMsg getList(String userId, String orderName,String orderCode, String productCode, Integer pageIndex, Integer pageSize,Integer isDelete) {
+        HttpRespMsg msg=new HttpRespMsg();
+        User user = userMapper.selectById(request.getHeader("token"));
+        List<Department> departments = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, user.getCompanyId()));
+        boolean viewAll = sysFunctionService.hasPriviledge(user.getRoleId(), "查看全部订单");
+        boolean viewDept = sysFunctionService.hasPriviledge(user.getRoleId(), "查看负责部门订单");
+        List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, user.getCompanyId()));
+        List<SysDict> sysDictOfOrderType = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, user.getCompanyId()).eq(SysDict::getCode, "OrderType"));
+        LambdaQueryWrapper<Order> orderLambdaQueryWrapper = new LambdaQueryWrapper<>();
+        orderLambdaQueryWrapper.eq(Order::getCompanyId,user.getCompanyId());
+        if(isDelete!=null){
+            orderLambdaQueryWrapper.eq(Order::getIsDelete,isDelete);
+        }else {
+            orderLambdaQueryWrapper.eq(Order::getIsDelete,0);
+        }
+        orderLambdaQueryWrapper.eq(Order::getStatus,1);
+        //判断查看全部的权限
+        if(!viewAll){
+            //判断查看负责部门的权限
+            if(!viewDept){
+                //都没有就只能看自己创建的
+                orderLambdaQueryWrapper.eq(Order::getCreatorId,user.getId());
+            }else {
+                List<Department> departmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getManagerId, user.getId()));
+                List<DepartmentOtherManager> otherManagerList = departmentOtherManagerMapper.selectList(new LambdaQueryWrapper<DepartmentOtherManager>().eq(DepartmentOtherManager::getOtherManagerId, user.getId()));
+                List<Integer> deptIds=new ArrayList<>();
+                deptIds.add(-1);
+                List<Integer> managerDeptIds = departmentList.stream().map(Department::getDepartmentId).distinct().collect(Collectors.toList());
+                List<Integer> otherManagerDeptIds = otherManagerList.stream().map(DepartmentOtherManager::getDepartmentId).distinct().collect(Collectors.toList());
+                deptIds.addAll(managerDeptIds);
+                List<Integer> finalDeptIds1 = deptIds;
+                managerDeptIds.forEach(m->{
+                    List<Integer> branchDepartment = getBranchDepartment(m, departments);
+                    finalDeptIds1.addAll(branchDepartment);
+                });
+                deptIds.addAll(otherManagerDeptIds);
+                List<Integer> finalDeptIds = deptIds;
+                otherManagerDeptIds.forEach(o->{
+                    List<Integer> branchDepartment = getBranchDepartment(o, departments);
+                    finalDeptIds.addAll(branchDepartment);
+                });
+                deptIds=deptIds.stream().distinct().collect(Collectors.toList());
+                List<Integer> finalDeptIds2 = deptIds;
+                List<String> userIds = userList.stream().filter(u -> finalDeptIds2.contains(u.getDepartmentId())).map(User::getId).collect(Collectors.toList());
+                orderLambdaQueryWrapper.in(Order::getCreatorId,userIds);
+            }
+        }
+        if(!StringUtils.isEmpty(orderName)){
+            orderLambdaQueryWrapper.like(Order::getOrderName,orderName);
+        }
+        if(!StringUtils.isEmpty(orderCode)){
+            orderLambdaQueryWrapper.like(Order::getOrderCode,orderCode);
+        }
+        if(!StringUtils.isEmpty(productCode)){
+            orderLambdaQueryWrapper.inSql(Order::getId,
+                    "select o.order_id from order_product_detail o left join product p on o.product_id=p.id " +
+                            "where p.company_id="+user.getCompanyId()+" and p.product_code like '%"+productCode+"%'");
+        }
+        if(pageIndex==null||pageSize==null){
+            pageIndex=-1;
+            pageSize=-1;
+        }
+        IPage<Order> orderIPage = orderMapper.selectPage(new Page<>(pageIndex, pageSize), orderLambdaQueryWrapper);
+        List<Order> records = orderIPage.getRecords();
+        records.forEach(r->{
+            Optional<User> item = userList.stream().filter(u -> u.getId().equals(r.getCreatorId())).findFirst();
+            if(item.isPresent()){
+                r.setInchargerName(item.get().getName());
+            }
+            Optional<SysDict> type = sysDictOfOrderType.stream().filter(u -> u.getId().equals(r.getCreatorId())).findFirst();
+            if(type.isPresent()){
+                r.setTypeName(type.get().getName());
+            }
+        });
+        Map map=new HashMap();
+        map.put("record",records);
+        map.put("total",orderIPage.getTotal());
+        msg.setData(map);
+        return msg;
+    }
+
+    //递归获取子部门
+    public List<Integer> getBranchDepartment(Integer departmentId, List<Department> departmentList) {
+        List<Integer> list = new ArrayList<>();
+        list.add(departmentId);
+        //搜到子部门进行添加
+        for (Department department : departmentList) {
+            if (departmentId.equals(department.getSuperiorId())) {
+                list.addAll(getBranchDepartment(department.getDepartmentId(), departmentList));
+            }
+        }
+        return list;
+    }
 }

+ 58 - 4
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/ProductServiceImpl.java

@@ -7,12 +7,10 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.management.platform.entity.*;
-import com.management.platform.mapper.ProductMapper;
-import com.management.platform.mapper.SysDictMapper;
-import com.management.platform.mapper.SysFormMapper;
-import com.management.platform.mapper.UserMapper;
+import com.management.platform.mapper.*;
 import com.management.platform.service.ProductService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.management.platform.service.SysFunctionService;
 import com.management.platform.service.WxCorpInfoService;
 import com.management.platform.util.ExcelUtil;
 import com.management.platform.util.HttpRespMsg;
@@ -37,6 +35,7 @@ import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.stream.Collectors;
 import java.util.zip.DataFormatException;
 
 /**
@@ -66,15 +65,56 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
     private SysDictMapper sysDictMapper;
     @Resource
     private ExcelExportServiceImpl excelExportService;
+    @Resource
+    private SysFunctionService sysFunctionService;
+    @Resource
+    private DepartmentMapper departmentMapper;
+    @Resource
+    private DepartmentOtherManagerMapper departmentOtherManagerMapper;
 
     @Override
     public HttpRespMsg getList(Integer companyId,String userId, String productName, String productCode, Integer pageIndex, Integer pageSize) {
         HttpRespMsg msg=new HttpRespMsg();
+        User targetUsr = userMapper.selectById(request.getHeader("token"));
+        List<Department> departments = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getCompanyId, companyId));
         LambdaQueryWrapper<Product> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.eq(Product::getCompanyId,companyId);
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
         List<SysDict> sysDictOfProductType = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "ProductType"));
         List<SysDict> sysDictOfProductUnit = sysDictMapper.selectList(new LambdaQueryWrapper<SysDict>().eq(SysDict::getCompanyId, companyId).eq(SysDict::getCode, "ProductUnit"));
+        boolean hasPriviledgeAll = sysFunctionService.hasPriviledge(targetUsr.getRoleId(), "查看全部产品数据");
+        boolean hasPriviledgeDept = sysFunctionService.hasPriviledge(targetUsr.getRoleId(), "查看负责部门产品数据");
+        //判断查看全部的权限
+        if(!hasPriviledgeAll){
+            //判断查看负责部门的权限
+            if(!hasPriviledgeDept){
+                //都没有就只能看自己创建的
+                queryWrapper.eq(Product::getCreatorId,targetUsr.getId());
+            }else {
+                List<Department> departmentList = departmentMapper.selectList(new LambdaQueryWrapper<Department>().eq(Department::getManagerId, targetUsr.getId()));
+                List<DepartmentOtherManager> otherManagerList = departmentOtherManagerMapper.selectList(new LambdaQueryWrapper<DepartmentOtherManager>().eq(DepartmentOtherManager::getOtherManagerId, targetUsr.getId()));
+                List<Integer> deptIds=new ArrayList<>();
+                deptIds.add(-1);
+                List<Integer> managerDeptIds = departmentList.stream().map(Department::getDepartmentId).distinct().collect(Collectors.toList());
+                List<Integer> otherManagerDeptIds = otherManagerList.stream().map(DepartmentOtherManager::getDepartmentId).distinct().collect(Collectors.toList());
+                deptIds.addAll(managerDeptIds);
+                List<Integer> finalDeptIds1 = deptIds;
+                managerDeptIds.forEach(m->{
+                    List<Integer> branchDepartment = getBranchDepartment(m, departments);
+                    finalDeptIds1.addAll(branchDepartment);
+                });
+                deptIds.addAll(otherManagerDeptIds);
+                List<Integer> finalDeptIds = deptIds;
+                otherManagerDeptIds.forEach(o->{
+                    List<Integer> branchDepartment = getBranchDepartment(o, departments);
+                    finalDeptIds.addAll(branchDepartment);
+                });
+                deptIds=deptIds.stream().distinct().collect(Collectors.toList());
+                List<Integer> finalDeptIds2 = deptIds;
+                List<String> userIds = userList.stream().filter(u -> finalDeptIds2.contains(u.getDepartmentId())).map(User::getId).collect(Collectors.toList());
+                queryWrapper.in(Product::getCreatorId,userIds);
+            }
+        }
         if(!StringUtils.isEmpty(userId)){
             queryWrapper.eq(Product::getCreatorId,userId);
         }
@@ -362,4 +402,18 @@ public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> impl
         String fileName="产品表导出_"+ System.currentTimeMillis();
         return excelExportService.exportGeneralExcelByTitleAndList(wxCorpInfo,fileName,dataList,path);
     }
+
+    //递归获取子部门
+    public List<Integer> getBranchDepartment(Integer departmentId, List<Department> departmentList) {
+        List<Integer> list = new ArrayList<>();
+        list.add(departmentId);
+        //搜到子部门进行添加
+        for (Department department : departmentList) {
+            if (departmentId.equals(department.getSuperiorId())) {
+                list.addAll(getBranchDepartment(department.getDepartmentId(), departmentList));
+            }
+        }
+        return list;
+    }
+
 }

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


Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików