Procházet zdrojové kódy

✨ CRM:完善回款 plan 详情

YunaiV před 1 rokem
rodič
revize
fee444d191

+ 7 - 0
src/api/crm/receivable/plan/index.ts

@@ -11,9 +11,16 @@ export interface ReceivablePlanVO {
   remindDays: number
   remindTime: Date
   customerId: number
+  customerName?: string
   contractId: number
+  contractNo?: string
   ownerUserId: number
+  ownerUserName?: string
   remark: string
+  creator: string // 创建人
+  creatorName?: string // 创建人名称
+  createTime: Date // 创建时间
+  updateTime: Date // 更新时间
   receivable?: {
     price: number
     returnTime: Date

+ 11 - 0
src/router/modules/remaining.ts

@@ -539,6 +539,17 @@ const remainingRouter: AppRouteRecordRaw[] = [
         },
         component: () => import('@/views/crm/contract/detail/index.vue')
       },
+      {
+        path: 'receivable-plan/detail/:id',
+        name: 'CrmReceivablePlanDetail',
+        meta: {
+          title: '回款计划详情',
+          noCache: true,
+          hidden: true,
+          activeMenu: '/crm/contract'
+        },
+        component: () => import('@/views/crm/receivable/plan/detail/index.vue')
+      },
       {
         path: 'contact/detail/:id',
         name: 'CrmContactDetail',

+ 44 - 0
src/views/crm/receivable/plan/detail/ReceivablePlanDetailsHeader.vue

@@ -0,0 +1,44 @@
+<template>
+  <div>
+    <div class="flex items-start justify-between">
+      <div>
+        <el-col>
+          <el-row>
+            <span class="text-xl font-bold">第 {{ receivablePlan.period }} 期</span>
+          </el-row>
+        </el-col>
+      </div>
+      <div>
+        <!-- 右上:按钮 -->
+        <slot></slot>
+      </div>
+    </div>
+  </div>
+  <ContentWrap class="mt-10px">
+    <el-descriptions :column="5" direction="vertical">
+      <el-descriptions-item label="客户名称">
+        {{ receivablePlan.customerName }}
+      </el-descriptions-item>
+      <el-descriptions-item label="合同编号">{{ receivablePlan.contractNo }}</el-descriptions-item>
+      <el-descriptions-item label="计划回款金额">
+        {{ erpPriceInputFormatter(receivablePlan.price) }}
+      </el-descriptions-item>
+      <el-descriptions-item label="计划回款日期">
+        {{ formatDate(receivablePlan.returnTime) }}
+      </el-descriptions-item>
+      <el-descriptions-item label="实际回款金额">
+        <el-text v-if="receivablePlan.receivable">
+          {{ erpPriceInputFormatter(receivablePlan.receivable.price) }}
+        </el-text>
+        <el-text v-else>{{ erpPriceInputFormatter(0) }}</el-text>
+      </el-descriptions-item>
+    </el-descriptions>
+  </ContentWrap>
+</template>
+<script lang="ts" setup>
+import * as ReceivablePlanApi from '@/api/crm/receivable/plan'
+import { formatDate } from '@/utils/formatTime'
+import { erpPriceInputFormatter } from '@/utils'
+
+const { receivablePlan } = defineProps<{ receivablePlan: ReceivablePlanApi.ReceivablePlanVO }>()
+</script>

+ 83 - 0
src/views/crm/receivable/plan/detail/ReceivablePlanDetailsInfo.vue

@@ -0,0 +1,83 @@
+<template>
+  <ContentWrap>
+    <el-collapse v-model="activeNames">
+      <el-collapse-item name="basicInfo">
+        <template #title>
+          <span class="text-base font-bold">基本信息</span>
+        </template>
+        <el-descriptions :column="4">
+          <el-descriptions-item label="期数">{{ receivablePlan.period }}</el-descriptions-item>
+          <el-descriptions-item label="客户名称">
+            {{ receivablePlan.customerName }}
+          </el-descriptions-item>
+          <el-descriptions-item label="合同编号">
+            {{ receivablePlan.contractNo }}
+          </el-descriptions-item>
+          <el-descriptions-item label="计划回款金额">
+            {{ erpPriceInputFormatter(receivablePlan.price) }}
+          </el-descriptions-item>
+          <el-descriptions-item label="计划回款日期">
+            {{ formatDate(receivablePlan.returnTime, 'YYYY-MM-DD') }}
+          </el-descriptions-item>
+          <el-descriptions-item label="计划回款方式">
+            <dict-tag
+              :type="DICT_TYPE.CRM_RECEIVABLE_RETURN_TYPE"
+              :value="receivablePlan.returnType"
+            />
+          </el-descriptions-item>
+          <el-descriptions-item label="提前几天提醒">
+            {{ receivablePlan.remindDays }}
+          </el-descriptions-item>
+          <el-descriptions-item label="备注">{{ receivablePlan.remark }}</el-descriptions-item>
+          <el-descriptions-item label="实际回款金额">
+            <el-text v-if="receivablePlan.receivable">
+              {{ erpPriceInputFormatter(receivablePlan.receivable.price) }}
+            </el-text>
+            <el-text v-else>{{ erpPriceInputFormatter(0) }}</el-text>
+          </el-descriptions-item>
+          <el-descriptions-item label="未回款金额">
+            <el-text v-if="receivablePlan.receivable">
+              {{ erpPriceInputFormatter(receivablePlan.price - receivablePlan.receivable.price) }}
+            </el-text>
+            <el-text v-else>{{ erpPriceInputFormatter(receivablePlan.price) }}</el-text>
+          </el-descriptions-item>
+          <el-descriptions-item label="实际回款日期">
+            {{ formatDate(receivablePlan.receivable?.returnTime, 'YYYY-MM-DD') }}
+          </el-descriptions-item>
+        </el-descriptions>
+      </el-collapse-item>
+      <el-collapse-item name="systemInfo">
+        <template #title>
+          <span class="text-base font-bold">系统信息</span>
+        </template>
+        <el-descriptions :column="4">
+          <el-descriptions-item label="负责人">
+            {{ receivablePlan.ownerUserName }}
+          </el-descriptions-item>
+          <el-descriptions-item label="创建人">
+            {{ receivablePlan.creatorName }}
+          </el-descriptions-item>
+          <el-descriptions-item label="创建时间">
+            {{ formatDate(receivablePlan.createTime) }}
+          </el-descriptions-item>
+          <el-descriptions-item label="更新时间">
+            {{ formatDate(receivablePlan.updateTime) }}
+          </el-descriptions-item>
+        </el-descriptions>
+      </el-collapse-item>
+    </el-collapse>
+  </ContentWrap>
+</template>
+<script setup lang="ts">
+import * as ReceivablePlanApi from '@/api/crm/receivable/plan'
+import { DICT_TYPE } from '@/utils/dict'
+import { formatDate } from '@/utils/formatTime'
+import { erpPriceInputFormatter } from '@/utils'
+
+const { receivablePlan } = defineProps<{
+  receivablePlan: ReceivablePlanApi.ReceivablePlanVO
+}>()
+
+// 展示的折叠面板
+const activeNames = ref(['basicInfo', 'systemInfo'])
+</script>

+ 103 - 0
src/views/crm/receivable/plan/detail/index.vue

@@ -0,0 +1,103 @@
+<template>
+  <ReceivablePlanDetailsHeader v-loading="loading" :receivable-plan="receivablePlan">
+    <el-button
+      v-if="permissionListRef?.validateWrite"
+      @click="openForm('update', receivablePlan.id)"
+    >
+      编辑
+    </el-button>
+  </ReceivablePlanDetailsHeader>
+  <el-col>
+    <el-tabs>
+      <el-tab-pane label="详细资料">
+        <ReceivablePlanDetailsInfo :receivable-plan="receivablePlan" />
+      </el-tab-pane>
+      <el-tab-pane label="操作日志">
+        <OperateLogV2 :log-list="logList" />
+      </el-tab-pane>
+      <el-tab-pane label="团队成员">
+        <PermissionList
+          ref="permissionListRef"
+          :biz-id="receivablePlan.id!"
+          :biz-type="BizTypeEnum.CRM_RECEIVABLE_PLAN"
+          :show-action="true"
+          @quit-team="close"
+        />
+      </el-tab-pane>
+    </el-tabs>
+  </el-col>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <ReceivablePlanForm ref="formRef" @success="getReceivablePlan(receivablePlan.id)" />
+</template>
+<script lang="ts" setup>
+import { useTagsViewStore } from '@/store/modules/tagsView'
+import * as ReceivablePlanApi from '@/api/crm/receivable/plan'
+import ReceivablePlanDetailsHeader from './ReceivablePlanDetailsHeader.vue'
+import ReceivablePlanDetailsInfo from './ReceivablePlanDetailsInfo.vue'
+import PermissionList from '@/views/crm/permission/components/PermissionList.vue' // 团队成员列表(权限)
+import { BizTypeEnum } from '@/api/crm/permission'
+import { OperateLogV2VO } from '@/api/system/operatelog'
+import { getOperateLogPage } from '@/api/crm/operateLog'
+import ReceivablePlanForm from '@/views/crm/receivable/plan/ReceivablePlanForm.vue'
+
+defineOptions({ name: 'CrmReceivablePlanDetail' })
+
+const message = useMessage()
+
+const receivablePlanId = ref(0) // 线索编号
+const loading = ref(true) // 加载中
+const receivablePlan = ref<ReceivablePlanApi.ReceivablePlanVO>(
+  {} as ReceivablePlanApi.ReceivablePlanVO
+) // 回款计划详情
+const permissionListRef = ref<InstanceType<typeof PermissionList>>() // 团队成员列表 Ref
+
+/** 获取详情 */
+const getReceivablePlan = async (id: number) => {
+  loading.value = true
+  try {
+    receivablePlan.value = await ReceivablePlanApi.getReceivablePlan(id)
+    await getOperateLog(id)
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 编辑 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
+}
+
+/** 获取操作日志 */
+const logList = ref<OperateLogV2VO[]>([]) // 操作日志列表
+const getOperateLog = async (receivablePlanId: number) => {
+  if (!receivablePlanId) {
+    return
+  }
+  const data = await getOperateLogPage({
+    bizType: BizTypeEnum.CRM_RECEIVABLE_PLAN,
+    bizId: receivablePlanId
+  })
+  logList.value = data.list
+}
+
+/** 关闭窗口 */
+const { delView } = useTagsViewStore() // 视图操作
+const { currentRoute } = useRouter() // 路由
+const close = () => {
+  delView(unref(currentRoute))
+}
+
+/** 初始化 */
+const { params } = useRoute()
+onMounted(async () => {
+  if (!params.id) {
+    message.warning('参数错误,回款计划不能为空!')
+    close()
+    return
+  }
+  receivablePlanId.value = params.id as unknown as number
+  await getReceivablePlan(receivablePlanId.value)
+})
+</script>

+ 13 - 3
src/views/crm/receivable/plan/index.vue

@@ -79,8 +79,13 @@
         </template>
       </el-table-column>
       <el-table-column align="center" label="合同编号" prop="contractNo" width="200px" />
-      <!-- TODO @puhui999:这里可以点到详情;最新版本,他有了单独的详情哈 -->
-      <el-table-column align="center" label="期数" prop="period" />
+      <el-table-column align="center" label="期数" prop="period">
+        <template #default="scope">
+          <el-link :underline="false" type="primary" @click="openDetail(scope.row.id)">
+            {{ scope.row.period }}
+          </el-link>
+        </template>
+      </el-table-column>
       <el-table-column
         align="center"
         label="计划回款金额(元)"
@@ -289,8 +294,13 @@ const handleExport = async () => {
   }
 }
 
-/** 打开客户详情 */
+/** 打开详情 */
 const { push } = useRouter()
+const openDetail = (id: number) => {
+  push({ name: 'CrmReceivablePlanDetail', params: { id } })
+}
+
+/** 打开客户详情 */
 const openCustomerDetail = (id: number) => {
   push({ name: 'CrmCustomerDetail', params: { id } })
 }