diff --git a/build/admin.tar.gz b/build/admin.tar.gz index 77bfe02..ed1ebfd 100644 --- a/build/admin.tar.gz +++ b/build/admin.tar.gz diff --git a/config/routers/crm_new.ts b/config/routers/crm_new.ts index 81934e8..c7ed32a 100644 --- a/config/routers/crm_new.ts +++ b/config/routers/crm_new.ts @@ -53,4 +53,12 @@ export default [ path: '/crm/recordDetail/:recordId', // 第三方渠道导入记录详情 component: './crm_new/ChannelImport/subpages/RecordDetail', }, + { + path: '/crm/tragetProportion', // 目标和占比设置 + component: './crm_new/TargetAndProportion', + }, + { + path: '/crm/addTragetProportion', // 添加目标和占比设置 + component: './crm_new/TargetAndProportion/subpages/AddNewSetting', + }, ]; \ No newline at end of file diff --git a/config/routers/order3.ts b/config/routers/order3.ts index cb8199f..8a4b24c 100644 --- a/config/routers/order3.ts +++ b/config/routers/order3.ts @@ -202,4 +202,8 @@ export default [ path: "/order3/orderSetting/deliveryVideoConfig", component: "./order3/OrderSetting/DeliveryVideoConfig", }, + { // 零售线索占比配置 + path: "/order3/retailTaskConfiguration", + component: "./order3/RetailTaskConfiguration", + }, ]; \ No newline at end of file diff --git a/src/components/ShopSelectNew/api.ts b/src/components/ShopSelectNew/api.ts index 9cd91c2..b04a70b 100644 --- a/src/components/ShopSelectNew/api.ts +++ b/src/components/ShopSelectNew/api.ts @@ -1,23 +1,26 @@ /* * @Date: 2021-07-08 16:53:36 * @LastEditors: wangqiang@feewee.cn - * @LastEditTime: 2022-05-25 11:32:53 + * @LastEditTime: 2022-10-08 16:17:27 */ import { http } from "@/typing/http"; import request from "@/utils/request"; import { OOP_HOST } from "@/utils/host"; import { LabelValueType } from "rc-tree-select/lib/interface"; -export interface QueryParams { - type: 1 | 2; // 1 集团维度 2 自定义门店维度 - shops?: string; // 门店集合 ,分割 - keywords?: string; // 门店关键字搜索 +export interface ShopSelectNewOptions { bizTypes?: string; // 业态类型集合 ,分割 brands?: string; // 品牌id集合 ,分割 regions?: string; // 区域编码集合 ,分割 dealers?: string; // 商家id集合 ,分割 } +export interface QueryParams extends ShopSelectNewOptions { + type: 1 | 2; // 1 集团维度 2 自定义门店维度 + shops?: string; // 门店集合 ,分割 + keywords?: string; // 门店关键字搜索 +} + export interface ShopItem { shopId?: number; //门店id shopFullName?: string; //门店全称 diff --git a/src/components/ShopSelectNew/components/ShopModal.tsx b/src/components/ShopSelectNew/components/ShopModal.tsx index 78246ad..d6722f6 100644 --- a/src/components/ShopSelectNew/components/ShopModal.tsx +++ b/src/components/ShopSelectNew/components/ShopModal.tsx @@ -2,7 +2,7 @@ * @Author: wangqiang@feewee.cn * @Date: 2022-05-25 10:03:00 * @LastEditors: wangqiang@feewee.cn - * @LastEditTime: 2022-06-10 15:57:29 + * @LastEditTime: 2022-10-08 16:33:31 */ import { InitialReturn } from "@/hooks/useInitail"; import { @@ -29,6 +29,7 @@ import { Value, Option, QueryParams, + ShopSelectNewOptions, } from "../api"; interface Props { @@ -47,6 +48,7 @@ interface Props { multiple?: boolean; optionInitial: InitialReturn; listInitial: InitialReturn; + defaultOptions?: ShopSelectNewOptions; } export default function ShopModal({ @@ -62,6 +64,7 @@ export default function ShopModal({ multiple, optionInitial, listInitial, + defaultOptions = {}, }: Props) { const fetchListByName = debounce( (keywords) => listInitial.setParams({ type, keywords }, true), @@ -245,14 +248,26 @@ export default function ShopModal({ ? listInitial.params.bizTypes.split(",") : undefined } - onChange={(bizs) => listInitial.setParams({ type, bizTypes: bizs?.join(",") }, true)} + onChange={(bizs) => listInitial.setParams( + { + type, + bizTypes: bizs.length + ? bizs?.join(",") + : defaultOptions.bizTypes, + }, + true + )} showSearch optionFilterProp="children" style={{ minWidth: 260, marginBottom: 10, marginRight: 10 }} getPopupContainer={(triggerNode) => triggerNode.parentNode} > {optionInitial.data.bizList?.map((biz) => ( - + {biz.name} ))} @@ -266,14 +281,26 @@ export default function ShopModal({ ? listInitial.params.regions.split(",") : undefined } - onChange={(regions) => listInitial.setParams({ type, regions: regions?.join(",") }, true)} + onChange={(regions) => listInitial.setParams( + { + type, + regions: regions.length + ? regions?.join(",") + : defaultOptions.regions, + }, + true + )} showSearch optionFilterProp="children" style={{ minWidth: 260, marginBottom: 10, marginRight: 10 }} getPopupContainer={(triggerNode) => triggerNode.parentNode} > {optionInitial.data.regionList?.map((region) => ( - + {region.fullName} ))} @@ -288,7 +315,12 @@ export default function ShopModal({ : undefined } onChange={(brandList) => listInitial.setParams( - { type, brands: brandList?.join(",") }, + { + type, + brands: brandList.length + ? brandList?.join(",") + : defaultOptions.brands, + }, true )} showSearch @@ -297,7 +329,11 @@ export default function ShopModal({ getPopupContainer={(triggerNode) => triggerNode.parentNode} > {optionInitial.data.brandList?.map((brand) => ( - + {brand.name} ))} @@ -312,7 +348,12 @@ export default function ShopModal({ : undefined } onChange={(dealerList) => listInitial.setParams( - { type, dealers: dealerList?.join(",") }, + { + type, + dealers: dealerList.length + ? dealerList?.join(",") + : defaultOptions.dealers, + }, true )} showSearch @@ -321,7 +362,11 @@ export default function ShopModal({ getPopupContainer={(triggerNode) => triggerNode.parentNode} > {optionInitial.data.dealerList?.map((dealer) => ( - + {dealer.name} ))} diff --git a/src/components/ShopSelectNew/index.tsx b/src/components/ShopSelectNew/index.tsx index e32df34..2b87a28 100644 --- a/src/components/ShopSelectNew/index.tsx +++ b/src/components/ShopSelectNew/index.tsx @@ -2,7 +2,7 @@ * @Author: wangqiang@feewee.cn * @Date: 2022-05-25 09:14:31 * @LastEditors: wangqiang@feewee.cn - * @LastEditTime: 2022-07-12 09:41:43 + * @LastEditTime: 2022-10-08 16:36:39 */ import useInitial from "@/hooks/useInitail"; import { Tag } from "antd"; @@ -14,7 +14,12 @@ import React, { useImperativeHandle, useState, } from "react"; -import { Value, getShopListChooseOptionsApi, getShopListApi } from "./api"; +import { + Value, + getShopListChooseOptionsApi, + getShopListApi, + ShopSelectNewOptions, +} from "./api"; import Close from "./components/Close"; import ShopModal from "./components/ShopModal"; import "./style.less"; @@ -28,6 +33,14 @@ interface Props { placeholder?: string; type?: 1 | 2; // 1 集团维度 2 自定义门店维度 shopIds?: number[]; // 仅查询门店ID列表,与 type = 2 时搭配使用 + /** + * 默认筛选参数,下拉框中不可删除; + * 用于特殊业务,例如 售前CRM-零售任务 选择门店时,需要默认查询 新车销售 的门店信息,则传入 + defaultOptions={{ + bizTypes: "1", + }} + */ + defaultOptions?: ShopSelectNewOptions; } export interface ShopSelectNewRef { @@ -46,6 +59,7 @@ function ShopSelectNew( type = 1, disabled = false, shopIds, + defaultOptions = {}, }: Props, ref: Ref ) { @@ -62,6 +76,7 @@ function ShopSelectNew( [], { type, + ...defaultOptions, }, delay ); @@ -173,6 +188,7 @@ function ShopSelectNew( setVisible={setVisible} optionInitial={optionInitial} listInitial={listInitial} + defaultOptions={defaultOptions} /> )} diff --git a/src/pages/crm_new/TargetAndProportion/api.ts b/src/pages/crm_new/TargetAndProportion/api.ts new file mode 100644 index 0000000..c6495b4 --- /dev/null +++ b/src/pages/crm_new/TargetAndProportion/api.ts @@ -0,0 +1,65 @@ +import { http } from '@/typing/http'; +import request from '@/utils/request'; +import { CRM_HOST } from '@/utils/host'; + +export interface SaveParams { + id?: number // 配置id + shopList?: ShopList[] // 门店列表 + operationType?: number // 0删除 1新增 2更新 + clueAimExclusive?: number // 线索目标 专属线索转化率 + clueAimManufacturer?: number // 线索目标 厂家下发转化率配置 + clueAimBroker?: number // 经纪人推荐目标占比转化率配置 + clueAimCas?: number // 保有客推荐目标占比转化率配置 + clueAimStaff?: number // 员工推荐目标比 + clueAimVisit?: number // 定巡展车展目标比 + clueDealAim?: number // 计算线索到店目标:线索到店成交潜客转化率 + gatherAim?: number // 计算月集客目标集客转化率配置不能小于0 + gatherAimExclusive?: number // 专属线索转化集客目标要求月集客目标的不能小于0 + gatherLiveAimDirect?: number // 直播/短视频直接集客目标占比 + potentialAim?: number // 集客转潜客占比 + potentialAimExclusive?: number // 潜客转化率 +} + +export interface ShopList { + shopName?: string // 门店名称 + shopId?: number // 门店id +} + +export interface List { + id?: number // 配置id + shopName?: string // 门店名称 +} +/** + * @description: 查询配置列表 + */ +export function getListApi(): http.PromiseResp { + return request.get(`${CRM_HOST}/erp/config/find/aims/rate/list`); +} + +/** + * @description: 查询配置详情 + */ +export function getConfigApi(id?: number): http.PromiseResp { + return request.get(`${CRM_HOST}/erp/config/find/aims/rate/id`, {params: {id}}); +} + +/** + * @description: 目标和占比设置 新增、更新 + */ +export function fetchOperationApi(parmas: SaveParams): http.PromiseResp { + return request.post(`${CRM_HOST}/erp/config/edit/aims/rate/all`, parmas); +} + +/** + * @description: 删除配置 + */ +export function fetchDeleteConfigApi(id?: number): http.PromiseResp { + return request.post(`${CRM_HOST}/erp/config/delete/aim`, {id}, {contentType: 'form-urlencoded'}); +} + +/** + * @description: 查询门店 + */ +export function getShopListApi(): http.PromiseResp { + return request.get(`${CRM_HOST}/erp/config/find/aims/shop`); +} diff --git a/src/pages/crm_new/TargetAndProportion/components/List.tsx b/src/pages/crm_new/TargetAndProportion/components/List.tsx new file mode 100644 index 0000000..c1608ab --- /dev/null +++ b/src/pages/crm_new/TargetAndProportion/components/List.tsx @@ -0,0 +1,78 @@ +import React, { useState } from "react"; +import { Popconfirm, Table, message, Space } from "antd"; +import { history } from 'umi'; +import { SaveParams, fetchOperationApi, fetchDeleteConfigApi, List } from '../api'; +import {useStore} from '../index'; + +const Column = Table.Column; + +export default function Index() { + const { statusData, setStatusData, data, setLoading } = useStore(); + function handleToEdit(value: List, operationType: number) { + const state = {id: value.id, operationType}; + history.push({pathname: '/crm/addTragetProportion', state}); + } + + function handleToDelete(operationType: number, id?: number) { + fetchDeleteConfigApi(id) + .then(res => { + message.success(res.result); + setLoading(true); + }) + .catch(e => { + message.error(e.message); + }); + } + + function handleToShopDetail(value?: List) { + setStatusData({...statusData, shop: true, id: value?.id}); + } + + function handleToTargetDetail(value: List = {}) { + setStatusData({...statusData, target: true, id: value?.id}); + } + + return ( +
+ + handleToShopDetail(record)}>{record.shopName || '--'}} + /> + handleToTargetDetail(record)}>查看} + /> + { + return ( + + handleToEdit(record, 2)}>编辑 + handleToDelete(0, record.id)} + > + + 删除 + + + + ); + }} + /> +
+
+ ); +} diff --git a/src/pages/crm_new/TargetAndProportion/components/ShopModal.tsx b/src/pages/crm_new/TargetAndProportion/components/ShopModal.tsx new file mode 100644 index 0000000..16272db --- /dev/null +++ b/src/pages/crm_new/TargetAndProportion/components/ShopModal.tsx @@ -0,0 +1,61 @@ +import React, {useEffect, useState} from 'react'; +import {Modal, Button, List, message} from 'antd'; +import { useStore } from '../index'; +import { getConfigApi, SaveParams } from '../api'; +import styles from '../index.less'; + +interface Data { + data: SaveParams + loading: boolean +} +export default function Index() { + const { statusData, setStatusData } = useStore(); + const [data, setData] = useState({data: {}, loading: false}); + function handleCancel() { + setStatusData({...statusData, shop: false, id: undefined}); + } + + useEffect(() => { + if (statusData.shop && statusData.id) { + setData({...data, loading: true}); + getConfigApi(statusData.id) + .then(res => { + setData({data: res.data || {}, loading: false}); + message.success(res.result); + }) + .catch(e => { + setData({data: {}, loading: false}); + message.error(e.message); + }); + } + }, [statusData.shop]); + + return ( + 适用门店} + visible={statusData.shop} + maskClosable={false} + onCancel={handleCancel} + footer={[]} + className={styles.modal} + > + {item.shopName}} + /> +
+
+
+ ); +} \ No newline at end of file diff --git a/src/pages/crm_new/TargetAndProportion/components/TargetModal.tsx b/src/pages/crm_new/TargetAndProportion/components/TargetModal.tsx new file mode 100644 index 0000000..9025261 --- /dev/null +++ b/src/pages/crm_new/TargetAndProportion/components/TargetModal.tsx @@ -0,0 +1,90 @@ +import React, {useState, useEffect} from 'react'; +import {Modal, message, Button, Row, Col} from 'antd'; +import { useStore } from '../index'; +import { isNil } from 'lodash'; +import { getConfigApi, SaveParams } from '../api'; +import styles from '../index.less'; + +interface Data { + data: SaveParams + loading: boolean +} + +export default function Index() { + const { statusData, setStatusData } = useStore(); + const [data, setData] = useState({data: {}, loading: false}); + + useEffect(() => { + if (statusData.target && statusData.id) { + setData({...data, loading: true}); + getConfigApi(statusData.id) + .then(res => { + setData({data: res.data || {}, loading: false}); + message.success(res.result); + }) + .catch(e => { + setData({data: {}, loading: false}); + message.error(e.message); + }); + } + }, [statusData.target]); + + function handleCancel() { + setStatusData({...statusData, target: false}); + } + + function renderData(value?: number) { + const _value = isNil(value) ? "--" : `${(value*100).toFixed(2)}%`; + return _value; + } + return ( + 目标占比} + visible={statusData.target} + maskClosable={false} + onCancel={handleCancel} + footer={[]} + width={800} + > +
+ <> +

线索

+

计算线索目标:专属线索转化率{renderData(data.data?.clueAimExclusive)}

+ + 线索目标占比设置: + +

厂家下发线索目标占比{renderData(data.data?.clueAimManufacturer)}经纪人推荐目标占比{renderData(data.data?.clueAimBroker)}

+

保有客推荐目标占比{renderData(data.data?.clueAimCas)}员工推荐目标占比{renderData(data.data?.clueAimStaff)}

+

定巡展车展目标占比{renderData(data.data?.clueAimVisit)}

+ +
+ + + <> +

集客

+

计算月集客目标:集客转化率{renderData(data.data?.gatherAim)}

+

月集客目标中:专属线索转集客占比{renderData(data.data?.gatherAimExclusive)}

+

直接集客目标中:直播/短视频直接集客目标占比{renderData(data.data?.gatherLiveAimDirect)}

+ + + <> +

潜客

+

月潜客目标中:集客转潜客占比{renderData(data.data?.potentialAim)}

+

计算月集客目标:潜客转化率{renderData(data.data?.potentialAimExclusive)}

+

计算线索到店目标:线索到店成交潜客转化率{renderData(data.data?.clueDealAim)}

+ +
+ +
+
+
+ ); +} \ No newline at end of file diff --git a/src/pages/crm_new/TargetAndProportion/index.less b/src/pages/crm_new/TargetAndProportion/index.less new file mode 100644 index 0000000..309c361 --- /dev/null +++ b/src/pages/crm_new/TargetAndProportion/index.less @@ -0,0 +1,59 @@ +.title { + font-size: 18px; + color: #333; + font-weight: 600; +} + +.warp { + display: flex; + direction: row; + align-items: flex-start; + justify-content: flex-start; +} + +.wrapItem { + display: inline-block; +} + +.text { + color: #333; + font-size: 14px; + font-weight: 500; +} + +.textTitle { + color: #333; + font-size: 14px; + font-weight: 400; +} + +.modal { + height: 400px; +} + +.line { + width: 4px; + height: 20px; + background-color: #4189FD; + border-radius: 2px; + display: inline-block; +} +.lineText { + font-size: 18px; + color: #262626; + font-weight: bold; + display: inline-block; + margin-left: 8px; +} + +.lineWrap { + display: flex; + align-items: center; +} + +.lineSpace { + margin-bottom: 10px; + font-size: 14px; + color: #333; + font-weight: 500; +} \ No newline at end of file diff --git a/src/pages/crm_new/TargetAndProportion/index.tsx b/src/pages/crm_new/TargetAndProportion/index.tsx new file mode 100644 index 0000000..e653fab --- /dev/null +++ b/src/pages/crm_new/TargetAndProportion/index.tsx @@ -0,0 +1,34 @@ +import React, {useEffect, useState} from 'react'; +import { Card, Button, Row } from 'antd'; +import { PageHeaderWrapper } from '@ant-design/pro-layout'; +import { createStore } from '@/hooks/moz'; +import store from './store'; +import List from './components/List'; +import { history } from 'umi'; +import ShopModal from './components/ShopModal'; +import TargetModal from './components/TargetModal'; + +export const { Provider, useStore } = createStore(store); + +function Index() { + const { loading } = useStore(); + function handleToAdd() { + const state = { operationType: 1}; + history.push({pathname: '/crm/addTragetProportion', state}); + } + + return ( + + + + + + + + + + + ); +} + +export default () => ; diff --git a/src/pages/crm_new/TargetAndProportion/store.ts b/src/pages/crm_new/TargetAndProportion/store.ts new file mode 100644 index 0000000..d60a2ac --- /dev/null +++ b/src/pages/crm_new/TargetAndProportion/store.ts @@ -0,0 +1,22 @@ +import React, { useState } from 'react'; +import useInitail from '@/hooks/useInitail'; +// import useInitial from '@/hooks/useInitail'; +import { getListApi } from './api'; + +interface StatusData { + shop: boolean // 门店显示 + target: boolean // 目标和占比显示 + id?: number +} +export default function useStore() { + const [statusData, setStatusData] = useState({shop: false, target: false, id: undefined}); + const { data, loading, errMsg, setLoading } = useInitail(getListApi, [], null); + return { + statusData, + setStatusData, + data, + loading, + errMsg, + setLoading, + }; +} \ No newline at end of file diff --git a/src/pages/crm_new/TargetAndProportion/subpages/AddNewSetting/index.tsx b/src/pages/crm_new/TargetAndProportion/subpages/AddNewSetting/index.tsx new file mode 100644 index 0000000..4b067bb --- /dev/null +++ b/src/pages/crm_new/TargetAndProportion/subpages/AddNewSetting/index.tsx @@ -0,0 +1,322 @@ +import React, { useState, useEffect } from 'react'; +import { Button, Form, message, InputNumber, Divider, Card, Row, Col, Select} from 'antd'; +import ShopSelectNew from '@/components/ShopSelectNew'; +import { PageHeaderWrapper } from '@ant-design/pro-layout'; +import { history } from 'umi'; +import { SaveParams, fetchOperationApi, getConfigApi, getShopListApi } from '../../api'; +import { debounce } from 'lodash'; +import currency from 'currency.js'; +import useInitail from '@/hooks/useInitail'; + +enum TitleEnum { + "新增" =1, + "编辑" +} + +const Option = Select.Option; + +export default function ApplyModal() { + const {id, operationType=1} = history.location.state as SaveParams || {}; + const [form] = Form.useForm(); + const [loading, setLoading] = useState(false); + const tip = "厂家下发线索目标占比+经纪人推荐目标占比+保有客推荐目标占比+员工推荐目标占比+定巡展车展目标占比之和需等于100"; + // const { data: shop } = useInitail(getShopListApi, [], null); + + useEffect(() => { + if (operationType === 2) { + getConfigApi(id) + .then(res => { + const {clueAimExclusive=0, clueAimManufacturer=0, clueAimBroker=0, clueAimCas=0, clueAimStaff=0, gatherAim=0, gatherAimExclusive=0, gatherLiveAimDirect=0, potentialAim=0, potentialAimExclusive=0, clueAimVisit=0, shopList, clueDealAim=0} = res.data || {}; + form.setFieldsValue({ + clueAimExclusive: (clueAimExclusive*100).toFixed(2), + clueAimManufacturer: (clueAimManufacturer*100).toFixed(2), + clueAimBroker: (clueAimBroker*100).toFixed(2), + clueAimCas: (clueAimCas*100).toFixed(2), + clueAimStaff: (clueAimStaff*100).toFixed(2), + clueAimVisit: (clueAimVisit*100).toFixed(2), + gatherAim: (gatherAim*100).toFixed(2), + gatherAimExclusive: (gatherAimExclusive*100).toFixed(2), + gatherLiveAimDirect: (gatherLiveAimDirect*100).toFixed(2), + potentialAim: (potentialAim*100).toFixed(2), + potentialAimExclusive: (potentialAimExclusive*100).toFixed(2), + clueDealAim: (clueDealAim*100).toFixed(2), + shopList: shopList?.map(v => ({label: v.shopName, value: v.shopId})) + }); + }) + .catch(e => { + message.error(e.message); + }); + } + }, [operationType]); + + async function onSubmit() { + const params = await form.validateFields(); + const count = currency(params.clueAimManufacturer) + .add(params.clueAimBroker) + .add(params.clueAimCas) + .add(params.clueAimStaff) + .add(params.clueAimVisit).value; + if (count !=100) { + message.error(tip); + return; + } + const shopList = params.shopList.map((v:any) => ({shopName: v.label, shopId: v.value})); + const _params: SaveParams = { + clueAimExclusive: +(params.clueAimExclusive / 100).toFixed(4), + clueAimManufacturer: +(params.clueAimManufacturer / 100).toFixed(4), + clueAimBroker: +(params.clueAimBroker / 100).toFixed(4), + clueAimCas: +(params.clueAimCas / 100).toFixed(4), + clueAimStaff: +(params.clueAimStaff /100).toFixed(4), + clueAimVisit: +(params.clueAimVisit /100).toFixed(4), + gatherAim: +(params.gatherAim / 100).toFixed(4), + gatherAimExclusive: +(params.gatherAimExclusive /100).toFixed(4), + gatherLiveAimDirect: +(params.gatherLiveAimDirect /100).toFixed(4), + potentialAim: +(params.potentialAim /100).toFixed(4), + potentialAimExclusive: +(params.potentialAimExclusive /100).toFixed(4), + clueDealAim: +(params.clueDealAim /100).toFixed(4), + shopList, + id, + operationType + }; + setLoading(true); + fetchOperationApi(_params) + .then(res => { + message.success(res.result); + setLoading(false); + history.goBack(); + }) + .catch(e => { + message.error(e.message); + setLoading(false); + }); + } + + function handleBack() { + history.goBack(); + } + + return ( + + +
+ + + + {/* + + */} + 线索 + + + `${value}%`} + precision={2} + parser={value => value?.replace('%', '')} + /> + + + `${value}%`} + precision={2} + parser={value => value?.replace('%', '')} + /> + + + `${value}%`} + precision={2} + parser={value => value?.replace('%', '')} + /> + + + `${value}%`} + precision={2} + parser={value => value?.replace('%', '')} + /> + + + `${value}%`} + precision={2} + parser={value => value?.replace('%', '')} + /> + + + `${value}%`} + precision={2} + parser={value => value?.replace('%', '')} + /> + + + 集客 + + `${value}%`} + precision={2} + parser={value => value?.replace('%', '')} + /> + + + `${value}%`} + precision={2} + parser={value => value?.replace('%', '')} + /> + + + `${value}%`} + precision={2} + parser={value => value?.replace('%', '')} + /> + + + 潜客 + + `${value}%`} + precision={2} + parser={value => value?.replace('%', '')} + /> + + + `${value}%`} + precision={2} + parser={value => value?.replace('%', '')} + /> + + + + `${value}%`} + precision={2} + parser={value => value?.replace('%', '')} + /> + +
+ + + + + + + + + + + + + + + +
+ +
+ ); +} \ No newline at end of file diff --git a/src/pages/order3/RetailManualAdjust/api.ts b/src/pages/order3/RetailManualAdjust/api.ts index 6befa6c..44eafd8 100644 --- a/src/pages/order3/RetailManualAdjust/api.ts +++ b/src/pages/order3/RetailManualAdjust/api.ts @@ -3,26 +3,30 @@ import request from '@/utils/request'; import { ORDER3 } from '@/utils/host'; export interface ListItem { - totalTaskCount?: number,//任务总数 + totalTaskCount?: number, //任务总数 shopTaskList?: ShopTaskList[], - year?: number,//年份 + year?: number, //年份 id?: number, - month?: number,//月份 + month?: number, //月份 canModified?: boolean//是否可调整 } export interface ShopTaskList { - shopId?: number,//门店id - shopName?: string,//门店名称 - taskCount?: number,//任务数量 + shopId?: number, //门店id + shopName?: string, //门店名称 + taskCount?: number, //任务数量 + clueDealTaskCount?: number // 线索到店零售台数 + clueDealTaskRate?: number // 线索到店零售占比 staffTaskList?: StaffTaskList[]//员工任务列表 } interface StaffTaskList { - staffId?: number,//员工id - staffName?: string,//员工名称 - taskCount?: number,//任务数量 + id?: number + staffId?: number, //员工id + staffName?: string, //员工名称 + taskCount?: number, //任务数量 regularMonth?: number//转正几个月 + clueDealTaskCount?: number // 线索到店零售台数 } export interface saveParams { id?: number, @@ -45,4 +49,3 @@ export function autoAlloctionApi(params: saveParams) { export function save(id?: number) { return request.post(`${ORDER3}/erp/sales/task/submit`, { id }, { contentType: 'form-urlencoded' }); } - diff --git a/src/pages/order3/RetailManualAdjust/component/Modal.tsx b/src/pages/order3/RetailManualAdjust/component/Modal.tsx index ef47b51..ace6d83 100644 --- a/src/pages/order3/RetailManualAdjust/component/Modal.tsx +++ b/src/pages/order3/RetailManualAdjust/component/Modal.tsx @@ -1,7 +1,8 @@ -import React, { useState } from 'react' -import { Row, Modal, Table, Button, InputNumber } from 'antd' -import Column from 'antd/lib/table/Column' +import React, { useState } from 'react'; +import { Row, Modal, Table, Button, InputNumber, message } from 'antd'; +import Column from 'antd/lib/table/Column'; import { ShopTaskList, ListItem } from '../api'; +import { isNil } from 'lodash'; interface Props { setVisible: any, @@ -17,16 +18,48 @@ interface Props { export default function EModal({ setVisible, visible, current = {}, index, setList, list = {}, setCurrent, isHandledit }: Props) { const [editable, setEditable] = useState(false); + /** + * 修改零售任务 + * @param e + * @param innerIndex + */ function _onChange(e: number, innerIndex: number) { //改变整体外层数据 - const data = list; - index && e && (data.shopTaskList![index].staffTaskList![innerIndex].taskCount = e); - index && setList({ ...data }); + const data = JSON.parse(JSON.stringify(list)); + const currentData = JSON.parse(JSON.stringify(current)); + if (!isNil(index) && e) { + data.shopTaskList![index].staffTaskList![innerIndex].taskCount = e; + data.shopTaskList![index].staffTaskList![innerIndex].clueDealTaskCount = Math.ceil((data.shopTaskList![index].clueDealTaskRate || 0)/100 *(e || 0)); + currentData.staffTaskList![innerIndex].taskCount = e; + currentData.staffTaskList![innerIndex].clueDealTaskCount = Math.ceil((data.shopTaskList![index].clueDealTaskRate || 0)/100 *(e || 0)); + } + setList({ ...data }); //回显改变数据 - const currentData = current; - currentData.staffTaskList![innerIndex].taskCount = e; setCurrent({ ...currentData }); } + + /** + * 修改线索到店零售台数 + * @param e + * @param innerIndex + */ + function hanldeChangeClue(e: number, innerIndex: number) { + //改变整体外层数据 + const data = JSON.parse(JSON.stringify(list)); + const currentData = JSON.parse(JSON.stringify(current)); + if (!isNil(index) && data.shopTaskList![index].staffTaskList[innerIndex].taskCount < e) { + message.error("线索到店零售台数不能大于零售任务!"); + return; + } + if (!isNil(index) && e) { + data.shopTaskList![index].staffTaskList![innerIndex].clueDealTaskCount = e; + currentData.staffTaskList![innerIndex].clueDealTaskCount = e; + } + setList({ ...data }); + //回显改变数据 + setCurrent({ ...currentData }); + } + function handleClick() { setVisible(false); setEditable(false); @@ -46,33 +79,44 @@ export default function EModal({ setVisible, visible, current = {}, index, setLi rowKey="staffId" pagination={false} > - { if (value.regularMonth) { - return {value.staffName}(转正第{value.regularMonth}个月) + return {value.staffName}(转正第{value.regularMonth}个月); } else { - return {value.staffName} + return {value.staffName}; } }} /> - { if (editable) { - return _onChange(e, index)} /> + return _onChange(e, index)} />; } else { - return {value} + return {value}; } }} /> + {value}} + /> - {isHandledit ? + {isHandledit ? ( <> - - - : null - } + + + + ) : null} - ) + ); } \ No newline at end of file diff --git a/src/pages/order3/RetailManualAdjust/index.tsx b/src/pages/order3/RetailManualAdjust/index.tsx index 5ffe834..a385bac 100644 --- a/src/pages/order3/RetailManualAdjust/index.tsx +++ b/src/pages/order3/RetailManualAdjust/index.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { PageHeaderWrapper } from '@ant-design/pro-layout'; import { Card, Table, Button, Row, DatePicker, Col, InputNumber, message } from 'antd'; import { getRetailManualList, ListItem, autoAlloctionApi, ShopTaskList, save, saveParams } from './api'; @@ -24,7 +24,8 @@ export default function TacklingCarModels() { const [edit, setEdit] = useState(false); const [list, setList] = useState({}); const [orginDara, setOrginDara] = useState({}); - let index; + const index = useRef(); + // let index; useEffect(() => { getList(newDay); @@ -53,9 +54,30 @@ export default function TacklingCarModels() { }); } + /** + * 修改零售任务台数 + * @param e + * @param index + */ function _onChange(e: number, index: number) { - const data = list; + const data = JSON.parse(JSON.stringify(list)); data.shopTaskList![index].taskCount = e; + data.shopTaskList![index].clueDealTaskCount = Math.ceil((e || 0)*((data.shopTaskList![index].clueDealTaskRate || 0)/100)); + setList({ ...data }); + } + + /** + * 修改线索到店零售台数 + * @param e + * @param index + */ + function handleChangeClue(e: number, index: number) { + const data = JSON.parse(JSON.stringify(list)); + if (data.shopTaskList[index].taskCount < e) { + message.error("线索到店零售台数不能大于零售任务!"); + return; + } + data.shopTaskList![index].clueDealTaskCount = e; setList({ ...data }); } @@ -73,6 +95,7 @@ export default function TacklingCarModels() { }; autoAllocationSave(params); } + //提交审批 function saveClick() { setLoading(true); @@ -88,6 +111,7 @@ export default function TacklingCarModels() { setSaveLoading(false); }); } + //自动提交 function autoAllocationSave(params: saveParams) { setConfirmLoading(true); @@ -135,8 +159,11 @@ export default function TacklingCarModels() { ); }} > - - + { if (edit) { return _onChange(e, index)} />; @@ -145,30 +172,35 @@ export default function TacklingCarModels() { } }} /> - ( + {value}} + /> + ( <> - + )} /> - + {list.canModified ? ( <> {edit ? : - - } + } {edit ? null : - - } + } {edit ? : - null - } + null} ) : null} diff --git a/src/pages/order3/RetailTask/api.ts b/src/pages/order3/RetailTask/api.ts index 3fa790e..0dd8861 100644 --- a/src/pages/order3/RetailTask/api.ts +++ b/src/pages/order3/RetailTask/api.ts @@ -3,25 +3,28 @@ import request from '@/utils/request'; import { ORDER3 } from '@/utils/host'; export interface ListItem { - totalTaskCount?: number,//任务总数 + totalTaskCount?: number, //任务总数 shopTaskList?: ShopTaskList[], - year?: number,//年份 + year?: number, //年份 id?: number, - month?: number,//月份 + month?: number, //月份 canModified?: boolean//是否可调整 } export interface ShopTaskList { - shopId?: number,//门店id - shopName?: string,//门店名称 - taskCount?: number,//任务数量 + shopId?: number//门店id + shopName?: string//门店名称 + taskCount?: number//任务数量 + clueDealTaskCount?: number // 线索到店零售台数 + clueDealTaskRate?: number // 线索到店零售占比 staffTaskList?: StaffTaskList[]//员工任务列表 } interface StaffTaskList { - staffId?: number,//员工id - staffName?: string,//员工名称 - taskCount?: number,//任务数量 + staffId?: number//员工id + staffName?: string//员工名称 + taskCount?: number//任务数量 + clueDealTaskCount?: number // 线索到店零售台数 regularMonth?: number//转正几个月 } export interface saveParams { @@ -44,5 +47,4 @@ export function saveHandelTack(params: saveParams) { /*提交 */ export function save(id?: number) { return request.post(`${ORDER3}/erp/sales/task/submit`, { id }, { contentType: 'form-urlencoded' }); -} - +} \ No newline at end of file diff --git a/src/pages/order3/RetailTask/component/Modal.tsx b/src/pages/order3/RetailTask/component/Modal.tsx index bf91f3a..69e9534 100644 --- a/src/pages/order3/RetailTask/component/Modal.tsx +++ b/src/pages/order3/RetailTask/component/Modal.tsx @@ -1,7 +1,8 @@ -import React, { useState } from 'react' -import { Row, Modal, Table, Button, InputNumber } from 'antd' -import Column from 'antd/lib/table/Column' +import React, { useState } from 'react'; +import { Row, Modal, Table, Button, InputNumber, message } from 'antd'; +import Column from 'antd/lib/table/Column'; import { ShopTaskList, ListItem } from '../api'; +import { isNil } from 'lodash'; interface Props { setVisible: any, @@ -19,14 +20,41 @@ export default function EModal({ setVisible, visible, current = {}, index, setLi function _onChange(e: number, innerIndex: number) { //改变整体外层数据 - const data = list; - index && e && (data.shopTaskList![index].staffTaskList![innerIndex].taskCount = e); - index && setList({ ...data }); + const data = JSON.parse(JSON.stringify(list)); + const currentData = JSON.parse(JSON.stringify(current)); + if (!isNil(index)) { + data.shopTaskList![index].staffTaskList![innerIndex].taskCount = e || 0; + data.shopTaskList![index].staffTaskList![innerIndex].clueDealTaskCount = Math.ceil((data.shopTaskList![index].clueDealTaskRate || 0)/100 *(e || 0)); + currentData.staffTaskList![innerIndex].taskCount = e || 0; + currentData.staffTaskList![innerIndex].clueDealTaskCount = Math.ceil((data.shopTaskList![index].clueDealTaskRate || 0)/100 *(e || 0)); + } + setList({ ...data }); //回显改变数据 - const currentData = current; - currentData.staffTaskList![innerIndex].taskCount = e || 0; setCurrent({ ...currentData }); } + + /** + * 修改零售任务 + * @param e + * @param innerIndex + */ + function hanldeChangeClue(e: number, innerIndex: number) { + //改变整体外层数据 + const data = JSON.parse(JSON.stringify(list)); + const currentData = JSON.parse(JSON.stringify(current)); + if (!isNil(index) && data.shopTaskList![index].staffTaskList[innerIndex].taskCount < e) { + message.error("线索到店零售台数不能大于零售任务!"); + return; + } + if (!isNil(index)) { + data.shopTaskList![index].staffTaskList![innerIndex].clueDealTaskCount = e || 0; + currentData.staffTaskList![innerIndex].clueDealTaskCount = e || 0; + } + setList({ ...data }); + //回显改变数据 + setCurrent({ ...currentData }); + } + function handleClick() { setVisible(false); setEditable(false); @@ -51,9 +79,9 @@ export default function EModal({ setVisible, visible, current = {}, index, setLi align="center" render={(value: any) => { if (value.regularMonth) { - return {value.staffName}(转正第{value.regularMonth}个月) + return {value.staffName}(转正第{value.regularMonth}个月); } else { - return {value.staffName} + return {value.staffName}; } }} /> @@ -63,9 +91,21 @@ export default function EModal({ setVisible, visible, current = {}, index, setLi align="center" render={(value, record, index) => { if (editable) { - return _onChange(e, index)} /> + return _onChange(e, index)} />; + } else { + return {value}; + } + }} + /> + { + if (editable) { + return hanldeChangeClue(e, index)} />; } else { - return {value} + return {value}; } }} /> @@ -79,5 +119,5 @@ export default function EModal({ setVisible, visible, current = {}, index, setLi ) : null} - ) + ); } \ No newline at end of file diff --git a/src/pages/order3/RetailTask/index.tsx b/src/pages/order3/RetailTask/index.tsx index f04ef3d..4cf17e7 100644 --- a/src/pages/order3/RetailTask/index.tsx +++ b/src/pages/order3/RetailTask/index.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import { PageHeaderWrapper } from '@ant-design/pro-layout'; import { Card, Table, Button, Row, DatePicker, Col, InputNumber, message } from 'antd'; import { getRetailList, ListItem, saveHandelTack, ShopTaskList, save, saveParams } from './api'; @@ -24,7 +24,7 @@ export default function TacklingCarModels() { const [date, setDate] = useState(newDay); const [list, setList] = useState({}); const [orginDara, setOrginDara] = useState({}); - let index; + const index = useRef(0); useEffect(() => { getList(newDay); @@ -57,9 +57,26 @@ export default function TacklingCarModels() { setDate(date.valueOf()); getList(date); } + function _onChange(e: number, index: number) { - const data = list; + const data = JSON.parse(JSON.stringify(list)); data.shopTaskList![index].taskCount = e || 0; + data.shopTaskList![index].clueDealTaskCount = Math.ceil((e || 0)*((data.shopTaskList![index].clueDealTaskRate || 0)/100)); + setList({ ...data }); + } + + /** + * 修改线索到店零售台数 + * @param e + * @param index + */ + function handleChangeClue(e: number, index: number) { + const data = JSON.parse(JSON.stringify(list)); + if (data.shopTaskList[index].taskCount < e) { + message.error("线索到店零售台数不能大于零售任务!"); + return; + } + data.shopTaskList![index].clueDealTaskCount = e || 0; setList({ ...data }); } //保存 @@ -121,54 +138,69 @@ export default function TacklingCarModels() { }); return ( <> - {total == 0 ? null : - + {total == 0 ? null : ( + 合计 {total} - + - } + )} ); }} > - { if (edit) { - return _onChange(e, index)} /> + return _onChange(e, index)} />; } else { - return {value} + return {value}; } }} /> - ( + { + if (edit) { + return handleChangeClue(e, index)} />; + } else { + return {value}; + } + }} + /> + ( <> - + )} /> - + - {list.canModified ? + {list.canModified ? ( <> {edit ? : - - } + } {edit ? : - null - } - : null - } + null} + + ) : null} - - ) + + ); } \ No newline at end of file diff --git a/src/pages/order3/RetailTaskConfiguration/api.ts b/src/pages/order3/RetailTaskConfiguration/api.ts new file mode 100644 index 0000000..51d8468 --- /dev/null +++ b/src/pages/order3/RetailTaskConfiguration/api.ts @@ -0,0 +1,29 @@ +import { http } from '@/typing/http'; +import request from '@/utils/request'; +import { ORDER3 } from '@/utils/host'; + +export interface List { + id?: number // id + retailRate?: number // 线索到店零售占比 + shopList?: ShopList[] // 门店列表 + displayName?: string // 门店名称集合 +} + +export interface ShopList { + shopId?: number // 门店id + shopName?: string // 门店名称 +} +/** 获取列表 */ +export function getRetailListApi(): http.PromiseResp { + return request.get(`${ORDER3}/erp/clue/deal/rate/config/list`); +} + +/* 新增编辑线索到店零售占比配置*/ +export function saveRetailConfigApi(params?: List) { + return request.post(`${ORDER3}/erp/clue/deal/rate/config/save`, params); +} + +/* 删除线索到店零售占比配置*/ +export function fetchDeleteConfigApi(id?: number) { + return request.post(`${ORDER3}/erp/clue/deal/rate/config/delete`, { id }, { contentType: 'form-urlencoded' }); +} \ No newline at end of file diff --git a/src/pages/order3/RetailTaskConfiguration/components/EditMidal.tsx b/src/pages/order3/RetailTaskConfiguration/components/EditMidal.tsx new file mode 100644 index 0000000..fe2df51 --- /dev/null +++ b/src/pages/order3/RetailTaskConfiguration/components/EditMidal.tsx @@ -0,0 +1,104 @@ +import React, { useState, useEffect } from 'react'; +import { Button, Form, message, InputNumber, Select, Modal} from 'antd'; +import ShopSelectNew from '@/components/ShopSelectNew'; +import { debounce } from 'lodash'; +import currency from 'currency.js'; +import useInitail from '@/hooks/useInitail'; +import { useStore } from '../index'; +import { saveRetailConfigApi } from '../api'; + +const Option = Select.Option; + +export default function Index() { + const [form] = Form.useForm(); + const { visible, setVisible, current, setCurrent, setLoading } = useStore(); + const [confirm, setConfirm] = useState(false); + + useEffect(() => { + if (visible && current.id) { + handleSetValue(); + } + }, [visible]); + + function handleCancle() { + setVisible(false); + setCurrent({}); + } + + async function handleSubmit() { + const params = await form.validateFields(); + setConfirm(true); + const _params = { + id: current.id, + retailRate: params.retailRate, + shopList: params.shopList?.map((v: any) => ({shopId: v.value, shopName: v.label})) + }; + saveRetailConfigApi(_params) + .then(res => { + message.success(res.result); + setVisible(false); + setConfirm(false); + setLoading(true); + setCurrent({}); + }) + .catch(e => { + message.error(e.message); + setConfirm(false); + }); + } + + function handleSetValue() { + form.setFieldsValue({ + retailRate: current.retailRate, + shopList: current.shopList?.map(v => ({label: v.shopName, value: v.shopId})) + }); + } + return ( + form.setFieldsValue({shopList: [], retailRate: undefined})} + style={{minWidth: "500px"}} + footer={[ + , + + ]} + > +
+ + + + + + `${value}%`} + precision={2} + parser={value => value?.replace('%', '')} + /> + + +
+ +
+ ); +} \ No newline at end of file diff --git a/src/pages/order3/RetailTaskConfiguration/components/List.tsx b/src/pages/order3/RetailTaskConfiguration/components/List.tsx new file mode 100644 index 0000000..cbd0391 --- /dev/null +++ b/src/pages/order3/RetailTaskConfiguration/components/List.tsx @@ -0,0 +1,74 @@ +import React from "react"; +import { message, Popconfirm, Table, Space } from "antd"; +import { useStore } from '../index'; +import { fetchDeleteConfigApi, List } from '../api'; +import { isNil } from 'lodash'; + +const Column = Table.Column; + +export default function TableList() { + const {data, loading, setLoading, setVisible, setCurrent, setStatusData } = useStore(); + + function handleDelete(id?: number) { + fetchDeleteConfigApi(id) + .then(res => { + message.success(res.result); + setLoading(true); + }) + .catch(e => { + message.error(e.message); + }); + } + + function handleEdit(value?: List) { + setCurrent(value || {}); + setVisible(true); + } + + function handleLookShop(value: any = {}) { + setStatusData({visible: true, data: value.shopList || []}); + } + + return ( +
+ + handleLookShop(record)} style={{color: "#4189FD"}}>{_text}} + /> + {isNil(record?.retailRate) ? "--" : `${record.retailRate}%`}} + /> + { + return ( + + handleEdit(record)} style={{ display: "block", color: "#4189FD" }}>编辑 + handleDelete(record.id)} + > + 删除 + + + ); + }} + /> +
+
+ ); +} diff --git a/src/pages/order3/RetailTaskConfiguration/components/ShopModal.tsx b/src/pages/order3/RetailTaskConfiguration/components/ShopModal.tsx new file mode 100644 index 0000000..ec6406e --- /dev/null +++ b/src/pages/order3/RetailTaskConfiguration/components/ShopModal.tsx @@ -0,0 +1,39 @@ +import React, {useEffect, useState} from 'react'; +import {Modal, Button, List} from 'antd'; +import { useStore } from '../index'; +import styles from '../index.less'; + +export default function Index() { + const { statusData, setStatusData } = useStore(); + function handleCancel() { + setStatusData({visible: false, data: []}); + } + + return ( + 适用门店} + visible={statusData.visible} + maskClosable={false} + onCancel={handleCancel} + footer={[]} + className={styles.modal} + > + {item.shopName}} + /> +
+
+
+ ); +} \ No newline at end of file diff --git a/src/pages/order3/RetailTaskConfiguration/index.less b/src/pages/order3/RetailTaskConfiguration/index.less new file mode 100644 index 0000000..6c6605f --- /dev/null +++ b/src/pages/order3/RetailTaskConfiguration/index.less @@ -0,0 +1,51 @@ +.title { + font-size: 18px; + color: #333; + font-weight: 600; +} + +.warp { + display: flex; + direction: row; + align-items: flex-start; + justify-content: flex-start; +} + +.wrapItem { + display: inline-block; +} + +.text { + color: #333; + font-size: 14px; + font-weight: 600; +} + +.modal { + height: 400px; +} + +.line { + width: 4px; + height: 20px; + background-color: #4189FD; + border-radius: 2px; + display: inline-block; +} + +.lineText { + font-size: 18px; + color: #262626; + font-weight: bold; + display: inline-block; + margin-left: 8px; +} + +.lineWrap { + display: flex; + align-items: center; +} + +.lineSpace { + margin-bottom: 10px; +} \ No newline at end of file diff --git a/src/pages/order3/RetailTaskConfiguration/index.tsx b/src/pages/order3/RetailTaskConfiguration/index.tsx new file mode 100644 index 0000000..b402919 --- /dev/null +++ b/src/pages/order3/RetailTaskConfiguration/index.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { Card, Button, Row } from 'antd'; +import { PageHeaderWrapper } from '@ant-design/pro-layout'; +import { createStore } from '@/hooks/moz'; +import store from './store'; +import List from './components/List'; +import ShopModal from './components/ShopModal'; +import EditModal from './components/EditMidal'; + +export const { Provider, useStore } = createStore(store); + +function SubsidizedInterest() { + const {setVisible, setParams} = useStore(); + return ( + + + + + + + + + + + ); +} + +export default () => ; diff --git a/src/pages/order3/RetailTaskConfiguration/store.ts b/src/pages/order3/RetailTaskConfiguration/store.ts new file mode 100644 index 0000000..0ac5a36 --- /dev/null +++ b/src/pages/order3/RetailTaskConfiguration/store.ts @@ -0,0 +1,28 @@ +import React, { useState } from 'react'; +import usePagination from '@/hooks/usePagination'; +import useInitial from '@/hooks/useInitail'; +import { getRetailListApi, List, ShopList} from './api'; + +interface StatusData { + visible: boolean + data: ShopList[] +} + +export default function useStore() { + const { data, setParams, setLoading, loading } = useInitial(getRetailListApi, [], null); + const [visible, setVisible] = useState(false); + const [current, setCurrent] = useState({}); + const [statusData, setStatusData] = useState({visible: false, data: []}); + return { + data, + setParams, + setLoading, + loading, + visible, + setVisible, + current, + setCurrent, + statusData, + setStatusData + }; +} \ No newline at end of file diff --git a/src/pages/pms/entity.ts b/src/pages/pms/entity.ts index 05fa96c..30ec20c 100644 --- a/src/pages/pms/entity.ts +++ b/src/pages/pms/entity.ts @@ -151,13 +151,13 @@ export const partTypeData = [ export const typeReceiverObj: {[key: string]: string} = { '售后工单锁定': '服务', - '装潢订单锁定': '推荐', + '装潢零售锁定': '推荐', '调件锁定': '', '': '', }; export const typeSenderObj: {[key: string]: string} = { '售后工单锁定': '送修人', - '装潢订单锁定': '下单人', + '装潢零售锁定': '下单人', '调件锁定': '', '': '', }; diff --git a/src/pages/pms/storage/partShop/components/FlowDetailModal.tsx b/src/pages/pms/storage/partShop/components/FlowDetailModal.tsx index 54dac2d..e14f416 100644 --- a/src/pages/pms/storage/partShop/components/FlowDetailModal.tsx +++ b/src/pages/pms/storage/partShop/components/FlowDetailModal.tsx @@ -76,6 +76,7 @@ export default function Index({item = {}, visible, onCancel}: Props) { {!!obj.carName &&
{`车辆: ${obj.carName}`}
} {!!obj.vin &&
{`车架号: ${obj.vin}`}
} + {!!obj.plateNo &&
{`车牌号: ${obj.plateNo}`}
} {!!obj.supplierName &&
{`供应商: ${obj.supplierName}`}
} {!!obj.purchaseCnt &&
{`外采种类: ${obj.purchaseCnt}`}
} {!!obj.amount &&
{`外采金额: ${obj.amount}`}
} diff --git a/src/pages/stock/Systems/TicketIncreaseToBeDone/index.tsx b/src/pages/stock/Systems/TicketIncreaseToBeDone/index.tsx index b7ff8fe..ce74fd8 100644 --- a/src/pages/stock/Systems/TicketIncreaseToBeDone/index.tsx +++ b/src/pages/stock/Systems/TicketIncreaseToBeDone/index.tsx @@ -84,7 +84,7 @@ export default function TicketIncreaseToBeDone() { }; const columns = [ { - title: "推开增票代办", + title: "开增票待办", width: "25%", dataIndex: "appointShopName", },