Преглед изворни кода

feat: 重构客户新增服务记录

lanjianrong пре 4 година
родитељ
комит
670c204d5e

+ 1 - 1
src/components/RightContent/Book/components/UserList/index.tsx

@@ -72,7 +72,7 @@ const UesrList: React.FC<UserListProps> = ({ contacts, onlineList }) => {
                     style={{
                       backgroundImage: `url(${
                         (isDevMode() ? 'http://cld2qa.com' : 'http://zhcld.com') +
-                        (item.avatar ? item.avatar : '/global/img/avtra_2.jpg')
+                        (item.avatar ? item.avatar : '/resource/avatar/avtra_2.jpg')
                       })`,
                       backgroundSize: 'cover'
                     }}

+ 0 - 99
src/pages/Customer/Client/components/ClientDetail/LowerList.jsx

@@ -1,99 +0,0 @@
-import { Tabs, List, Row, Col, Table } from 'antd'
-import React from 'react'
-import { dayjsFormat } from '@/utils/utils'
-import consts from '@/consts'
-import { isDevMode } from '@/utils/env'
-
-export const servicelogEnum = {
-  1: '上门服务',
-  2: '电话拜访',
-  3: '其他事项',
-  4: '在线服务'
-}
-
-const ClientLowerList = props => {
-  const {
-    log: { log: logs = [] },
-    servicelist
-  } = props
-  const { TabPane } = Tabs
-  const columns = [
-    {
-      title: '日期',
-      dataIndex: 'createTime',
-      key: 'createTime',
-      width: 100
-    },
-    {
-      title: '操作人',
-      dataIndex: 'operatorName',
-      key: 'operatorName',
-      width: 115,
-      render: (_, record) => (
-        <div className="flex items-center flex-row ml-2">
-          <img
-            className="w-full max-w-30px h-30px border rounded-30px"
-            src={
-              (isDevMode() ? 'http://cld2qa.com' : 'http://zhcld.com') +
-              (record?.avatar ?? consts.DEFAULT_AVATAR)
-            }
-          />
-          <span className="ml-1">{record.operatorName}</span>
-        </div>
-      )
-    },
-    {
-      title: '操作',
-      dataIndex: 'operationType',
-      key: 'operationType',
-      width: 75
-    },
-    {
-      title: '操作内容',
-      dataIndex: 'content',
-      key: 'content',
-      width: 150
-    }
-  ]
-  return (
-    <div>
-      <div className="pl-4">
-        <Tabs>
-          <TabPane tab="客户服务记录" key="客户服务记录">
-            <div className="sheet-panel-record">
-              <Row>
-                <Col span="8">类型/时间</Col>
-                <Col span="16">服务内容</Col>
-              </Row>
-              <List
-                dataSource={servicelist}
-                split={false}
-                renderItem={item => (
-                  <List.Item>
-                    <Row className="w-full">
-                      <Col span="8">
-                        <a className="mr-1">@{item.staffName}</a>
-                        {servicelogEnum[item.status]}
-                        <List.Item.Meta description={dayjsFormat(item.date, 'YYYY-MM-DD')} />
-                      </Col>
-                      <Col span="16" className="whitespace-pre-line">
-                        {item.mark}
-                      </Col>
-                    </Row>
-                  </List.Item>
-                )}
-              />
-            </div>
-          </TabPane>
-          <TabPane tab="日志" key="日志">
-            <div className="sheet-panel-record">
-              <Table rowKey="id" columns={columns} dataSource={logs} pagination={false} />
-            </div>
-          </TabPane>
-        </Tabs>
-      </div>
-    </div>
-  )
-}
-
-export default ClientLowerList

+ 129 - 0
src/pages/Customer/Client/components/ClientDetail/LowerList.tsx

@@ -0,0 +1,129 @@
+import { Tabs, List } from 'antd'
+import React from 'react'
+import { dayjsFormat } from '@/utils/utils'
+import TimeLineList from '@/components/TimeLineList'
+import classNames from 'classnames'
+import { isDevMode } from '@/utils/env'
+
+export enum Servicelog {
+  /** 上门服务 */
+  VISIT = '1',
+  /** 电话拜访 */
+  CALL = '2',
+  /** 其他事项 */
+  OTHER = '3',
+  /** 在线服务 */
+  ONLINE = '4'
+}
+
+export const servicelogEnum = {
+  [Servicelog.VISIT]: {
+    title: '上门服务',
+    bg: 'bg-hex-886ab5 bg-opacity-6',
+    text: 'text-hex-886ab5 fomt-medium'
+  },
+  [Servicelog.CALL]: {
+    title: '电话拜访',
+    bg: 'bg-hex-246daf bg-opacity-6',
+    text: 'text-hex-246daf fomt-medium'
+  },
+  [Servicelog.OTHER]: {
+    title: '其他事项',
+    bg: 'bg-hex-b8795e bg-opacity-6',
+    text: 'text-hex-b8795e fomt-medium'
+  },
+  [Servicelog.ONLINE]: {
+    title: '在线服务',
+    bg: 'bg-hex-b8795e bg-opacity-6',
+    text: 'text-hex-b8795e fomt-medium'
+  }
+}
+
+type ClientLowerListProps = {
+  logList: {
+    log: any[]
+  }
+  serviceList: API.ServiceLogItem[]
+}
+const ClientLowerList: React.FC<ClientLowerListProps> = ({ logList: { log: logs = [] }, serviceList }) => {
+  const { TabPane } = Tabs
+
+  const renderServiceLogItem = (item: API.ServiceLogItem) => {
+    return (
+      <div
+        className={classNames(
+          'w-full rounded border-hex-886ab5 border-l-2px',
+          servicelogEnum[item.status]?.bg
+        )}>
+        <div className="p-4 flex flex-col">
+          <div className="flex justify-between">
+            <div className="flex">
+              <div
+                className="rounded-1/2 w-8 h-8"
+                style={{
+                  backgroundImage: `url(${
+                    (isDevMode() ? 'http://cld2qa.com' : 'http://zhcld.com') +
+                    (item.avatar ? item.avatar : '/resource/avatar/avtra_2.jpg')
+                  })`,
+                  backgroundSize: 'cover'
+                }}
+              />
+              <div className="flex flex-col items-center ml-2">
+                <div className="text-sm font-medium text-opacity-80 text-black">{item.staffName}</div>
+                <div className="text-xs text-opacity-40 text-black h-1rem">
+                  {dayjsFormat(item.createTime, 'HH:mm:ss')}
+                </div>
+              </div>
+            </div>
+            <div className={servicelogEnum[item.status]?.text}>{servicelogEnum[item.status]?.title}</div>
+          </div>
+          <div className="bg-white bg-opacity-80 rounded-sm text-black text-opacity-60 text-sm mt-4 p-2">
+            {item.mark}
+          </div>
+          <div className="pt-2 flex justify-between">
+            <div />
+            <div className="text-sm text-opacity-80">
+              <span>服务日期:</span>
+              <span className="ml-1">{dayjsFormat(item.date, 'YYYY-MM-DD')}</span>
+            </div>
+          </div>
+        </div>
+      </div>
+    )
+  }
+  return (
+    <div>
+      <div className="pl-4">
+        <Tabs>
+          <TabPane tab="客户服务记录" key="客户服务记录">
+            <div className="sheet-panel-record ">
+              <TimeLineList<API.ServiceLogItem>
+                rowkey="id"
+                mode="card"
+                dataField="createTime"
+                dataSource={serviceList}
+                renderItem={item => renderServiceLogItem(item)}
+              />
+            </div>
+          </TabPane>
+          <TabPane tab="日志" key="日志">
+            <div className="sheet-panel-record">
+              <List
+                dataSource={logs}
+                split={false}
+                renderItem={item => (
+                  <List.Item>
+                    <a>@{item.operatorName}</a> {item.content}
+                    <List.Item.Meta description={dayjsFormat(item.createTime)} />
+                  </List.Item>
+                )}
+              />
+            </div>
+          </TabPane>
+        </Tabs>
+      </div>
+    </div>
+  )
+}
+
+export default ClientLowerList

+ 4 - 4
src/pages/Customer/Client/components/ClientDetail/index.jsx

@@ -1,8 +1,8 @@
 import { Row, Col, Spin, Tooltip, Drawer } from 'antd'
 import React, { useState, useEffect } from 'react'
-import ClientForm from './Form.jsx'
-import ClientTabList from './TabList.jsx'
-import ClientLowerList from './LowerList.jsx'
+import ClientForm from './Form'
+import ClientTabList from './TabList'
+import ClientLowerList from './LowerList'
 import { apiClientDetail } from '@/services/customer'
 import consts from '@/consts'
 import { connect, useModel } from 'umi'
@@ -117,7 +117,7 @@ const ClientDetail = props => {
                   software={state.software}
                   updatePayload={{ main: updateKey, target: dataId }}
                 />
-                <ClientLowerList log={state.log} servicelist={state.serviceLog} />
+                <ClientLowerList logList={state.log} serviceList={state.serviceLog} />
               </Col>
             </Row>
           </div>

+ 108 - 106
src/pages/Workbench/Dashboard/index.jsx

@@ -295,7 +295,7 @@ const Dashboard = ({ dispatch, departments = [] }) => {
   return (
     <PageContainer title={false} breadcrumb={false} waterMarkProps={{ offsetTop: 111 }}>
       <div className={styles.dashboard}>
-        <div>
+        <div className="enter-y">
           <Row gutter={[8, 8]}>
             <Col xs={24} sm={24} md={24} lg={18} xl={18}>
               <div className="shadow-card">
@@ -338,7 +338,7 @@ const Dashboard = ({ dispatch, departments = [] }) => {
           </Row>
         </div>
 
-        <div className="flex flex-wrap">
+        <div className="flex flex-wrap enter-y">
           <div className="mr-4 my-4 flex">
             <Select
               disabled={state.disabled}
@@ -402,75 +402,76 @@ const Dashboard = ({ dispatch, departments = [] }) => {
               ))}
           </div>
         </div>
-        <Row gutter={[8, 8]}>
-          <Col xs={24} sm={24} md={24} lg={8} xl={8}>
-            <div className="p-4 bg-white border rounded-2px border-hex-f0f0f0 shadow-card">
-              {state.loading ? (
-                <Skeleton active avatar />
-              ) : (
-                <Row className="cursor-pointer" onClick={() => handleRatioCard(cardTypeMap.CLIENT)}>
-                  <Col span={6}>
-                    <div className="w-full max-w-48px h-48px border rounded-48px bg-[#0c7cd5] flex items-center justify-center">
-                      <AddressBook size="26" fill="#fff" />
-                    </div>
-                  </Col>
-                  <Col span={18} flex="wrap">
-                    <div className="flex items-center justify-between ">
-                      <div className="text-2xl">{state.clientChainRatio.count}</div>
-                      <span
-                        className={[
-                          'text-xl',
-                          state.clientChainRatio.percentage.startsWith('-')
-                            ? 'text-green-500'
-                            : 'text-red-500'
-                        ].join(' ')}>
-                        {state.clientChainRatio.percentage}
-                      </span>
-                    </div>
-                    <div className="flex justify-between items-center">
-                      <div>新增客户</div>
-                      <span>{cyclicalOp.find(item => item.value === state.params.cyclical)?.title}</span>
-                    </div>
-                  </Col>
-                </Row>
-              )}
-            </div>
-          </Col>
-          <Col xs={24} sm={24} md={24} lg={8} xl={8}>
-            <div className="p-4 bg-white border rounded-2px border-hex-f0f0f0 shadow-card">
-              {state.loading ? (
-                <Skeleton active avatar />
-              ) : (
-                <Row className="cursor-pointer" onClick={() => handleRatioCard(cardTypeMap.COMPANY)}>
-                  <Col span={6}>
-                    <div className="w-full max-w-48px h-48px border rounded-48px bg-[#0c7cd5] flex items-center justify-center">
-                      <City size="26" fill="#fff" />
-                    </div>
-                  </Col>
-                  <Col span={18} flex="wrap">
-                    <div className="flex items-center justify-between ">
-                      <div className="text-2xl">{state.customerChainRatio.count}</div>
-                      <span
-                        className={[
-                          'text-xl',
-                          state.customerChainRatio.percentage.startsWith('-')
-                            ? 'text-green-500'
-                            : 'text-red-500'
-                        ].join(' ')}>
-                        {state.customerChainRatio.percentage}
-                      </span>
-                    </div>
+        <div className="enter-y">
+          <Row gutter={[8, 8]}>
+            <Col xs={24} sm={24} md={24} lg={8} xl={8}>
+              <div className="p-4 bg-white border rounded-2px border-hex-f0f0f0 shadow-card">
+                {state.loading ? (
+                  <Skeleton active avatar />
+                ) : (
+                  <Row className="cursor-pointer" onClick={() => handleRatioCard(cardTypeMap.CLIENT)}>
+                    <Col span={6}>
+                      <div className="w-full max-w-48px h-48px border rounded-48px bg-[#0c7cd5] flex items-center justify-center">
+                        <AddressBook size="26" fill="#fff" />
+                      </div>
+                    </Col>
+                    <Col span={18} flex="wrap">
+                      <div className="flex items-center justify-between ">
+                        <div className="text-2xl">{state.clientChainRatio.count}</div>
+                        <span
+                          className={[
+                            'text-xl',
+                            state.clientChainRatio.percentage.startsWith('-')
+                              ? 'text-green-500'
+                              : 'text-red-500'
+                          ].join(' ')}>
+                          {state.clientChainRatio.percentage}
+                        </span>
+                      </div>
+                      <div className="flex justify-between items-center">
+                        <div>新增客户</div>
+                        <span>{cyclicalOp.find(item => item.value === state.params.cyclical)?.title}</span>
+                      </div>
+                    </Col>
+                  </Row>
+                )}
+              </div>
+            </Col>
+            <Col xs={24} sm={24} md={24} lg={8} xl={8}>
+              <div className="p-4 bg-white border rounded-2px border-hex-f0f0f0 shadow-card">
+                {state.loading ? (
+                  <Skeleton active avatar />
+                ) : (
+                  <Row className="cursor-pointer" onClick={() => handleRatioCard(cardTypeMap.COMPANY)}>
+                    <Col span={6}>
+                      <div className="w-full max-w-48px h-48px border rounded-48px bg-[#0c7cd5] flex items-center justify-center">
+                        <City size="26" fill="#fff" />
+                      </div>
+                    </Col>
+                    <Col span={18} flex="wrap">
+                      <div className="flex items-center justify-between ">
+                        <div className="text-2xl">{state.customerChainRatio.count}</div>
+                        <span
+                          className={[
+                            'text-xl',
+                            state.customerChainRatio.percentage.startsWith('-')
+                              ? 'text-green-500'
+                              : 'text-red-500'
+                          ].join(' ')}>
+                          {state.customerChainRatio.percentage}
+                        </span>
+                      </div>
 
-                    <div className="flex justify-between items-center">
-                      <div>新增单位</div>
-                      <span>{cyclicalOp.find(item => item.value === state.params.cyclical)?.title}</span>
-                    </div>
-                  </Col>
-                </Row>
-              )}
-            </div>
-          </Col>
-          {/* <Col xs={24} sm={24} md={24} lg={6} xl={6}>
+                      <div className="flex justify-between items-center">
+                        <div>新增单位</div>
+                        <span>{cyclicalOp.find(item => item.value === state.params.cyclical)?.title}</span>
+                      </div>
+                    </Col>
+                  </Row>
+                )}
+              </div>
+            </Col>
+            {/* <Col xs={24} sm={24} md={24} lg={6} xl={6}>
             <div className="p-4 bg-white border rounded-2px border-hex-f0f0f0 shadow-card">
               {state.loading ? (
                 <Skeleton active avatar />
@@ -508,42 +509,43 @@ const Dashboard = ({ dispatch, departments = [] }) => {
               )}
             </div>
           </Col> */}
-          <Col xs={24} sm={24} md={24} lg={8} xl={8}>
-            <div className="p-4 bg-white border rounded-2px border-hex-f0f0f0 shadow-card">
-              {state.loading ? (
-                <Skeleton active avatar />
-              ) : (
-                <Row onClick={() => handleRatioCard(cardTypeMap.SERVICE)} className="cursor-pointer">
-                  <Col span={6}>
-                    <div className="w-full max-w-48px h-48px border rounded-48px bg-[#0c7cd5] flex items-center justify-center">
-                      <Comment size="26" fill="#fff" />
-                    </div>
-                  </Col>
-                  <Col span={18} flex="wrap">
-                    <div className="flex items-center justify-between ">
-                      <div className="text-2xl">{state.serviceLogChainRatio.count}</div>
-                      <span
-                        className={[
-                          'text-xl',
-                          state.serviceLogChainRatio.percentage.startsWith('-')
-                            ? 'text-green-500'
-                            : 'text-red-500'
-                        ].join(' ')}>
-                        {state.serviceLogChainRatio.percentage}
-                      </span>
-                    </div>
+            <Col xs={24} sm={24} md={24} lg={8} xl={8}>
+              <div className="p-4 bg-white border rounded-2px border-hex-f0f0f0 shadow-card">
+                {state.loading ? (
+                  <Skeleton active avatar />
+                ) : (
+                  <Row onClick={() => handleRatioCard(cardTypeMap.SERVICE)} className="cursor-pointer">
+                    <Col span={6}>
+                      <div className="w-full max-w-48px h-48px border rounded-48px bg-[#0c7cd5] flex items-center justify-center">
+                        <Comment size="26" fill="#fff" />
+                      </div>
+                    </Col>
+                    <Col span={18} flex="wrap">
+                      <div className="flex items-center justify-between ">
+                        <div className="text-2xl">{state.serviceLogChainRatio.count}</div>
+                        <span
+                          className={[
+                            'text-xl',
+                            state.serviceLogChainRatio.percentage.startsWith('-')
+                              ? 'text-green-500'
+                              : 'text-red-500'
+                          ].join(' ')}>
+                          {state.serviceLogChainRatio.percentage}
+                        </span>
+                      </div>
 
-                    <div className="flex justify-between items-center">
-                      <div>服务记录</div>
-                      <span>{cyclicalOp.find(item => item.value === state.params.cyclical)?.title}</span>
-                    </div>
-                  </Col>
-                </Row>
-              )}
-            </div>
-          </Col>
-        </Row>
-        <div className="mt-4">
+                      <div className="flex justify-between items-center">
+                        <div>服务记录</div>
+                        <span>{cyclicalOp.find(item => item.value === state.params.cyclical)?.title}</span>
+                      </div>
+                    </Col>
+                  </Row>
+                )}
+              </div>
+            </Col>
+          </Row>
+        </div>
+        <div className="mt-4 enter-y">
           <Row gutter={[8, 8]}>
             {/* <Col xs={24} sm={24} md={24} lg={12} xl={12}>
             <BusinessChar
@@ -580,7 +582,7 @@ const Dashboard = ({ dispatch, departments = [] }) => {
             </Col>
           </Row>
         </div>
-        <div className="mt-4">
+        <div className="mt-4 enter-y">
           <Row gutter={[8, 8]}>
             <Col xs={24} sm={24} md={24} lg={12} xl={12}>
               <LeaderBoard dataList={state.leaderboard} loading={state.loading} />

+ 13 - 0
src/services/typding.d.ts

@@ -33,4 +33,17 @@ declare namespace API {
     hiredate: string
   }
   type ContractList = ContractItem[]
+
+  /** @description 服务记录 */
+  type ServiceLogItem = {
+    avatar?: string
+    date?: string
+    createTime?: string
+    id?: string
+    mark?: string
+    staffName?: string
+    status?: string
+  }
+
+  type ServiceLogList = ServiceLogItem[]
 }