Commit ca94efc581eeabe288dcfd5600359475ea93734e

Authored by 王强
2 parents 1ba40972 6f3d6ded

Merge branch 'bug_fix' into erp

Showing 32 changed files with 1551 additions and 250 deletions
build/admin.tar.gz
No preview for this file type
config/routers/cas.ts
... ... @@ -105,6 +105,10 @@ export default [
105 105 path: '/cas/Claim/firstInsuranceClaim', // 首保索赔价格配置
106 106 component: './cas/firstInsuranceClaim'
107 107 },
  108 + {
  109 + path: '/cas/Claim/PartGroup', // 配件分组
  110 + component: './cas/PartGroup'
  111 + },
108 112 // {
109 113 // path: '/cas/part/BorrowAndExport', //借料出库
110 114 // component: './cas/borrowExport'
... ... @@ -354,4 +358,15 @@ export default [
354 358 path: '/cas/YwManage/accessoryReplacement',
355 359 component: './cas/AccessoryReplacement'
356 360 },
  361 + /**
  362 + * 工单设置
  363 + */
  364 + {
  365 + path: '/cas/workOrder/base',
  366 + component: './cas/workOrder/base'
  367 + },
  368 + {
  369 + path: '/cas/workOrder/washCar',
  370 + component: './cas/workOrder/washCar'
  371 + },
357 372 ];
... ...
src/components/PositionSelector/index.tsx
... ... @@ -32,7 +32,7 @@ export default function PositionSelector({ value = {}, onChange, disabled, style
32 32  
33 33 function confirm(data: ValueParams) {
34 34 setVisible(false);
35   - onChange && onChange({...data })
  35 + onChange && onChange({...data });
36 36 }
37 37  
38 38 return (
... ... @@ -49,7 +49,7 @@ export default function PositionSelector({ value = {}, onChange, disabled, style
49 49 {!disabled && visible && (
50 50 <MapModal
51 51 cancel={() => setVisible(false)}
52   - info={(value.point) ? value : defaultAddress}
  52 + info={(value?.point) ? value : defaultAddress}
53 53 visible={visible}
54 54 ok={confirm}
55 55 />
... ...
src/pages/cas/PartGroup/api.ts 0 → 100644
  1 +import { http } from '@/typing/http';
  2 +import request from '@/utils/request';
  3 +import { CAS_HOST, HOST } from '@/utils/host';
  4 +
  5 +type PromisePageResp<T> = http.PromisePageResp<T>;
  6 +
  7 +interface ListParam {
  8 + current?: number,
  9 + pageSize?: number,
  10 + keyword?: string,
  11 + vin?: string,
  12 +}
  13 +
  14 +export interface ListVO {
  15 + /** 工单id */
  16 + id?: number,
  17 + /** 工单号 */
  18 + orderNo?: string,
  19 + /** 工单状态 */
  20 + status?: number,
  21 + /** 工单状态名称 */
  22 + statusName?: string,
  23 + /** 车辆名称 */
  24 + carName?: string,
  25 + /** 车牌号 */
  26 + plateNo?: string,
  27 + /** 接车时间 */
  28 + receiveTime?: number,
  29 + /** 服务站 */
  30 + shopId?: number,
  31 + shopName?: string,
  32 + /** 服务顾问 */
  33 + receiverName?: string,
  34 + /** 车型代码 */
  35 + specCode?: string
  36 + vin?: string,
  37 +}
  38 +
  39 +/** 获取接车列表 */
  40 +export function getListApi(params: ListParam): PromisePageResp<ListVO> {
  41 + return request.get(`${CAS_HOST}/erp/reception/cancel/notify/list`, { params });
  42 +}
  43 +
  44 +/** 结接车单 */
  45 +export function endApi(vin?: string): http.PromiseResp<string> {
  46 + return request.get(`${CAS_HOST}/erp/reception/cancel/notify`, { params: {vin} },);
  47 +}
... ...
src/pages/cas/PartGroup/components/AddModal.tsx 0 → 100644
  1 +import React, { useEffect, useState } from "react";
  2 +import { Modal, Form, Select, message, Input, Table, Button } from "antd";
  3 +import ItemSelect from "./ItemSelect";
  4 +import {PartItem} from './api';
  5 +import PartTable from './PartTable';
  6 +
  7 +const FormItem = Form.Item;
  8 +const { Option } = Select;
  9 +
  10 +interface Props {
  11 + visible: boolean;
  12 + item: any;
  13 + setVisible: (value: any) => any;
  14 + setLoading: (value: boolean) => any;
  15 + setItem: (value: any) => any;
  16 +}
  17 +
  18 +export default function AddModal(props: Props) {
  19 + const { visible, item, setVisible, setLoading, setItem } = props;
  20 + const [form] = Form.useForm();
  21 +
  22 + useEffect(() => {
  23 + console.log("item", item);
  24 + // if (item && item.id) {
  25 + // // form.setFieldsValue({});
  26 + // } else {
  27 + // form.resetFields();
  28 + // }
  29 + }, [visible]);
  30 +
  31 + function handleSave(value: any) {
  32 + const partList = form.getFieldValue("partList");
  33 + const params = {
  34 + partList,
  35 + partGroupName: value.partGroupName,
  36 + partGroupCode: value.partGroupCode,
  37 + };
  38 + console.log("pppp", params);
  39 + }
  40 +
  41 + const onClose = () => {
  42 + setItem({});
  43 + setVisible(false);
  44 + };
  45 +
  46 + return (
  47 + <Modal
  48 + visible={visible}
  49 + onCancel={() => onClose()}
  50 + width={820}
  51 + onOk={() => form.submit()}
  52 + // getContainer={false}
  53 + >
  54 + <Form
  55 + form={form}
  56 + labelCol={{ span: 5 }}
  57 + wrapperCol={{ span: 18 }}
  58 + onFinish={handleSave}
  59 + onValuesChange={(changeValue, values) => {}}
  60 + >
  61 + <FormItem
  62 + name="partGroupName"
  63 + label="配件分组名称"
  64 + rules={[{ required: true, message: "必填" }]}
  65 + >
  66 + <Input />
  67 + </FormItem>
  68 + <FormItem
  69 + name="partGroupCode"
  70 + label="配件分组代码"
  71 + rules={[{ required: true, message: "必填" }]}
  72 + >
  73 + <Input placeholder="大写英文加数字" />
  74 + </FormItem>
  75 + <FormItem
  76 + label="配件清单"
  77 + rules={[
  78 + {
  79 + required: true,
  80 + min: 1,
  81 + message: "配件清单不能为空",
  82 + type: "array",
  83 + },
  84 + ]}
  85 + shouldUpdate
  86 + name="partList"
  87 + >
  88 + <PartTable />
  89 + </FormItem>
  90 + </Form>
  91 + </Modal>
  92 + );
  93 +}
... ...
src/pages/cas/PartGroup/components/Filter.tsx 0 → 100644
  1 +import React, { useState } from 'react';
  2 +import { Row, Input, Radio, DatePicker, Select } from 'antd';
  3 +import { debounce } from 'lodash';
  4 +
  5 +interface Props {
  6 + onChange: (param: {}) => any,
  7 + innerParams: any
  8 +}
  9 +
  10 +const Search = Input.Search;
  11 +const Option = Select.Option;
  12 +
  13 +export default function Filter({ onChange, innerParams }: Props) {
  14 + const fetchListByNo = debounce(handleSearchByNo, 500);
  15 +
  16 + function handleSearchByNo(value: string) {
  17 + onChange && onChange({
  18 + vin: value || undefined
  19 + });
  20 + }
  21 +
  22 + return (
  23 + <Row style={{ width: "100%", marginBottom: 24 }}>
  24 + <Search
  25 + enterButton
  26 + allowClear
  27 + placeholder="搜索配件分组名称"
  28 + onChange={(e) => fetchListByNo(e.target.value)}
  29 + onSearch={handleSearchByNo}
  30 + style={{ maxWidth: 260 }}
  31 + defaultValue={innerParams.keyword}
  32 + />
  33 + </Row>
  34 + );
  35 +}
0 36 \ No newline at end of file
... ...
src/pages/cas/PartGroup/components/ItemSelect.tsx 0 → 100644
  1 +import React, { useState, useEffect } from "react";
  2 +import { Modal, Table, Input, Select } from "antd";
  3 +import * as api from "./api";
  4 +import usePagination from "@/hooks/usePagination";
  5 +import Column from "antd/lib/table/Column";
  6 +import { debounce } from "lodash";
  7 +import { RowSelectionType } from "antd/es/table/interface";
  8 +import { getBrandFilterApi } from "@/common/api";
  9 +import useInitail from "@/hooks/useInitail";
  10 +
  11 +const Search = Input.Search;
  12 +const { Option } = Select;
  13 +
  14 +interface Props {
  15 + visible: boolean;
  16 + onCancel: () => any;
  17 + onOk: (data: any) => any;
  18 + selected: api.PartItem[]
  19 + type: RowSelectionType;
  20 +}
  21 +
  22 +export default function ItemSelect(props: Props) {
  23 + const { visible, onCancel, onOk, type, selected } = props;
  24 + const { data: brands } = useInitail<CommonApi.OptionVO[], {}>(getBrandFilterApi, [], {});
  25 + const { list, loading, setParams, paginationConfig } = usePagination(
  26 + api.getPartItems,
  27 + { current: 1, pageSize: 10, keywords: "" }
  28 + );
  29 + const [selectData, setSelectData] = useState<api.PartItem[]>([]);
  30 +
  31 + useEffect(() => {
  32 + if (visible) {
  33 + setSelectData(
  34 + selected.map((item:any) => ({
  35 + ...item,
  36 + id: item.itemId || item.id,
  37 + }))
  38 + );
  39 + }
  40 + }, [visible]);
  41 +
  42 + const _onChange = debounce((value: any) => {
  43 + setParams({ keywords: value, current: 1 }, true);
  44 + }, 800);
  45 +
  46 + function handSave() {
  47 + if (selectData.length && onOk) {
  48 + onOk(
  49 + selectData.map((item) => ({
  50 + ...item,
  51 + itemId: item.id,
  52 + }))
  53 + );
  54 + }
  55 + }
  56 +
  57 + const handleChangeBrand = debounce((value) => {
  58 + setParams(value, true);
  59 + }, 500);
  60 +
  61 + return (
  62 + <Modal
  63 + visible={visible}
  64 + title="装潢件"
  65 + width={700}
  66 + onCancel={() => onCancel()}
  67 + onOk={handSave}
  68 + >
  69 + <Select
  70 + style={{ width: 150 }}
  71 + onChange={(value) => {
  72 + handleChangeBrand({ brandId: value });
  73 + }}
  74 + placeholder="请选择品牌"
  75 + allowClear
  76 + // defaultValue={28}
  77 + >
  78 + {brands.map((item: CommonApi.OptionVO) => (
  79 + <Option value={item.id} key={item.id}>
  80 + {item.name}
  81 + </Option>
  82 + ))}
  83 + </Select>
  84 + <Search
  85 + allowClear
  86 + onChange={(e) => _onChange(e.target.value)}
  87 + onSearch={(keywords) => setParams({ keywords }, true)}
  88 + style={{ width: 230, marginBottom: 10, marginLeft: 30 }}
  89 + placeholder="请输入配件名称/编码/件号"
  90 + />
  91 + <Table
  92 + loading={loading}
  93 + dataSource={list}
  94 + pagination={{ ...paginationConfig, showSizeChanger: false }}
  95 + rowKey="id"
  96 + rowSelection={{
  97 + type,
  98 + selectedRowKeys: selectData.map((item) => item.id || -1),
  99 + onSelect: (row: any, _selected: boolean) => {
  100 + const index = selectData.findIndex((_row) => _row.id == row.id);
  101 + if (_selected) {
  102 + selectData.unshift(row);
  103 + } else if (index > -1) {
  104 + selectData.splice(index, 1);
  105 + }
  106 + setSelectData([...selectData]);
  107 + },
  108 + onSelectAll: (selected, selectedRows, changeRows) => {
  109 + const changedKeys = changeRows.map((row) => row.id);
  110 + let newData = [...selectData];
  111 + // 全选
  112 + if (selected) {
  113 + // 过滤掉已选的
  114 + newData = selectData.concat(
  115 + changeRows.filter(
  116 + (row) => !selectData.some((item) => item.id == row.id)
  117 + )
  118 + );
  119 + } else {
  120 + // 全不选 - 去掉已选的
  121 + newData = selectData.filter(
  122 + (row) => !changedKeys.includes(row.id)
  123 + );
  124 + }
  125 + setSelectData(newData);
  126 + },
  127 + // onSelectInvert: () => {},
  128 + // onSelectMultiple: () => {},
  129 + }}
  130 + >
  131 + <Column title="配件编码" dataIndex="partCode" />
  132 + <Column title="配件件号" dataIndex="partNo" width={150} />
  133 + <Column title="配件名称" dataIndex="partName" />
  134 + </Table>
  135 + </Modal>
  136 + );
  137 +}
... ...
src/pages/cas/PartGroup/components/PartTable.tsx 0 → 100644
  1 +import { Button, Form, Table } from 'antd';
  2 +import * as React from 'react';
  3 +import {PartItem} from './api';
  4 +import ItemSelect from './ItemSelect';
  5 +import type { ColumnsType} from "antd/lib/table";
  6 +
  7 +export interface Props {
  8 + value?:PartItem[]
  9 + onChange?: (data: PartItem[]) => void
  10 +}
  11 +
  12 +const Index = (props:Props) => {
  13 + const {value=[], onChange} = props;
  14 + const [form] = Form.useForm();
  15 + const [visible, setVisible] = React.useState(false);
  16 +
  17 + const columns: ColumnsType<PartItem> = [
  18 + {
  19 + title: "配件名称",
  20 + dataIndex: "partName",
  21 + key: "partName",
  22 + align: "center",
  23 + },
  24 + {
  25 + title: "配件编码",
  26 + dataIndex: "partCode",
  27 + key: "partCode",
  28 + align: "center",
  29 + },
  30 + {
  31 + title: "操作",
  32 + render: (text: any, record: PartItem) => (
  33 + <Button
  34 + danger
  35 + onClick={() => {
  36 + const _list = value;
  37 + const partList = _list.filter((e) => e.partId != record.partId);
  38 + onChange && onChange([...partList]);
  39 + }}
  40 + >
  41 + 删除
  42 + </Button>
  43 + ),
  44 + },
  45 + ];
  46 +
  47 + const onSelect = (data: PartItem[]) => {
  48 + onChange && onChange(data);
  49 + setVisible(false);
  50 + }
  51 +
  52 + return (
  53 + <div>
  54 + <Button
  55 + type="primary"
  56 + style={{ marginBottom: 10 }}
  57 + onClick={() => setVisible(true)}
  58 + >
  59 + 新增
  60 + </Button>
  61 + <Form component={false} form={form}>
  62 + <Table
  63 + bordered
  64 + columns={columns}
  65 + dataSource={[...value]}
  66 + rowKey="id"
  67 + />
  68 + </Form>
  69 + <ItemSelect
  70 + visible={visible}
  71 + type="checkbox"
  72 + onOk={onSelect}
  73 + onCancel={() => setVisible(false)}
  74 + selected={[...value]}
  75 + />
  76 + </div>
  77 + );
  78 +}
  79 +
  80 +export default Index;
... ...
src/pages/cas/PartGroup/components/api.ts 0 → 100644
  1 +import { http } from '@/typing/http';
  2 +import request from '@/utils/request';
  3 +import { PMS_HOST } from '@/utils/host';
  4 +
  5 +type PromisePageResp<T> = http.PromisePageResp<T>;
  6 +
  7 +export interface PartItem {
  8 + id?: number,
  9 + partId?: number,
  10 + /**配件编码 */
  11 + partCode: string,
  12 + /**配件名称 */
  13 + partName: string,
  14 + /**配件号 */
  15 + partNo?: string,
  16 + /**配件数量 */
  17 + partNumber?: number,
  18 + [key: string]: any
  19 +}
  20 +export interface QueryParams {
  21 + current?: number,
  22 + pageSize?: number,
  23 + keywords?: string,
  24 + brandId?: number
  25 +}
  26 +
  27 +/**查询备件 */
  28 +export function getPartItems(params: QueryParams): PromisePageResp<PartItem> {
  29 + return request.get(`${PMS_HOST}/erp/part/list`, { params });
  30 +}
... ...
src/pages/cas/PartGroup/index.tsx 0 → 100644
  1 +import { PageHeaderWrapper } from '@ant-design/pro-layout';
  2 +import { Button, Card, message, Popconfirm, Table } from 'antd';
  3 +import * as React from 'react';
  4 +import Filter from "./components/Filter";
  5 +import * as api from "./api";
  6 +import usePagination from "@/hooks/usePagination";
  7 +import { PlusOutlined } from "@ant-design/icons";
  8 +import AddModal from './components/AddModal';
  9 +
  10 +const { Column } = Table;
  11 +
  12 +const Index = () => {
  13 + const {
  14 + list,
  15 + errMsg,
  16 + loading,
  17 + setLoading,
  18 + paginationConfig,
  19 + innerParams,
  20 + setParams,
  21 + } = usePagination(api.getListApi);
  22 +
  23 + const [visible, setVisible] = React.useState(false);
  24 + const [current, setCurrent] = React.useState({});
  25 +
  26 + function endOrder(row: api.ListVO) {
  27 + row.id &&
  28 + api
  29 + .endApi(row.vin)
  30 + .then((res) => {
  31 + message.success("禁用成功");
  32 + setLoading(true);
  33 + })
  34 + .catch((e) => {
  35 + message.error(`禁用失败:${e.message}`);
  36 + });
  37 + }
  38 +
  39 + const onFilter = (option: any = {}) => {
  40 + setParams({ ...innerParams, ...option, current: 1 }, true);
  41 + };
  42 + return (
  43 + <PageHeaderWrapper title="配件分组">
  44 + <Card>
  45 + <div
  46 + style={{
  47 + display: "flex",
  48 + flexDirection: "row",
  49 + justifyContent: "space-between",
  50 + alignItems: "center",
  51 + marginBottom: 20,
  52 + }}
  53 + >
  54 + <Filter innerParams={innerParams} onChange={onFilter} />
  55 + <Button type="primary" icon={<PlusOutlined />} onClick={() => setVisible(true)}>
  56 + 新增
  57 + </Button>
  58 + </div>
  59 + <Table
  60 + dataSource={list}
  61 + loading={loading}
  62 + pagination={paginationConfig}
  63 + rowKey="id"
  64 + >
  65 + <Column title="配件分组名称" dataIndex="vin" align="center" />
  66 + <Column
  67 + title="配件分组代码"
  68 + dataIndex="plateNo"
  69 + align="center"
  70 + render={(text) => <span>{text || "--"}</span>}
  71 + />
  72 + <Column
  73 + title="配件自动匹配关键词"
  74 + dataIndex="status"
  75 + align="center"
  76 + render={(text) => <span>{text || "--"}</span>}
  77 + />
  78 + <Column
  79 + title="配件清单"
  80 + dataIndex="hopeReceiverName"
  81 + align="center"
  82 + render={(text) => (
  83 + <Button type="primary" style={{ marginLeft: 10 }}>
  84 + 查看
  85 + </Button>
  86 + )}
  87 + />
  88 + <Column
  89 + title="操作"
  90 + align="center"
  91 + render={(t, row: api.ListVO) => (
  92 + <div>
  93 + <Button
  94 + size="small"
  95 + onClick={() => {
  96 + setVisible(true);
  97 + setCurrent(row);
  98 + }}
  99 + >编辑
  100 + </Button>
  101 + <Popconfirm title="确认禁用" onConfirm={() => endOrder(row)}>
  102 + <Button
  103 + danger
  104 + type="link"
  105 + size="small"
  106 + style={{ marginLeft: 10 }}
  107 + >
  108 + 删除
  109 + </Button>
  110 + </Popconfirm>
  111 + </div>
  112 + )}
  113 + />
  114 + </Table>
  115 + <AddModal item={current} setItem={setCurrent} visible={visible} setVisible={setVisible} setLoading={setLoading} />
  116 + </Card>
  117 + </PageHeaderWrapper>
  118 + );
  119 +};
  120 +
  121 +export default Index;
0 122 \ No newline at end of file
... ...
src/pages/cas/afterSaleConfiguration/jobManagement/components/CreateModal.tsx
... ... @@ -211,6 +211,9 @@ export default function SaveModal(props: Props) {
211 211 <Option value={7} key={7}>
212 212 洗车
213 213 </Option>
  214 + <Option value={8} key={8}>
  215 + 养护
  216 + </Option>
214 217 </Select>
215 218 </FormItem>
216 219 <FormItem
... ...
src/pages/cas/workOrder/base/api.ts 0 → 100644
  1 +import { http } from "@/typing/http";
  2 +import request from "@/utils/request";
  3 +import { ATTENDANCE_HOST } from '@/utils/host';
  4 +
  5 +type P<T> = http.PromiseResp<T>;
  6 +//type Page<T> = http.PromisePageResp<T>;
  7 +
  8 +export interface Item {
  9 + id?: number, // 配置id
  10 + monthRestCnt?: number, // 每月休息天数
  11 + scheduleDays?: number, // 下月排班表设置时间(当月倒数后多少天)
  12 + changeRestCnt?: number, // 主动调休次数
  13 + exceedChangePunishAmount?: number, // 超过调休次数罚款金额
  14 + missingCardPunishAmount?: number, // 缺卡罚款金额
  15 + latePunishAmount?: number, // 迟到罚款金额
  16 + seriousLatePunishAmount?: number, // 严重迟到罚款金额
  17 + missingCardCnt?: number, // 缺卡次数
  18 + lateCnt?: number, // 迟到次数
  19 + seriousLateCnt?: number, // 严重迟到次数(扣绩效分)
  20 + missingCardPunishScore?: number, // 缺卡超过N次扣绩效分
  21 + latePunishScore?: number, // 迟到超过N次扣绩效分
  22 + seriousLatePunishScore?: number, // 严重迟到超过N次扣绩效分
  23 + morningShiftPercent?: number, // 早晚班早班占比,百分比
  24 + absenteeismPunishScore?: number, // 旷工扣绩效分
  25 + restContinuousCnt?: number, // 排班连续休息最大天数
  26 + temporaryPunishAmount?: number, // 临时假罚款金额
  27 + absenteeismPunishAmount?: number, // 旷工罚款金额
  28 + verifyFaceRatio?: number, // 活体和人脸验证比例(百分比,整数)
  29 + sickLeavePunishAmount?: number, // 病假扣款标准(/天)
  30 + personalLeavePunishAmount?: number, // 事假扣款标准(/天)
  31 + continuousAbsent?: number, // 连续矿工次数(用于触发离职)
  32 + accumulativeAbsent?: number, // 月累计旷工次数(用于触发离职)
  33 +}
  34 +
  35 +/**查询考勤打卡基础配置*/
  36 +export function fetchDetail(): P<Item> {
  37 + return request.get(`${ATTENDANCE_HOST}/setting/clock/in/basic/info`);
  38 +}
  39 +
  40 +/**保存考勤打卡基础配置*/
  41 +export function saveApi(params?: Item) {
  42 + return request.post(`${ATTENDANCE_HOST}/setting/clock/in/basic/save`, params);
  43 +}
  44 +
  45 +export interface WashItem {
  46 + shopName: string
  47 + shopId: number
  48 + isWash: string
  49 + itemName: string
  50 + itemId: number
  51 +}
0 52 \ No newline at end of file
... ...
src/pages/cas/workOrder/base/components/WashList.tsx 0 → 100644
  1 +import { Button, Form, Table } from "antd";
  2 +import * as React from "react";
  3 +import { WashItem } from "../api";
  4 +import WashModal from "./WashModal";
  5 +import type { ColumnsType } from "antd/lib/table";
  6 +
  7 +export interface Props {
  8 + value?: WashItem[];
  9 + onChange?: (data: WashItem[]) => void;
  10 + edit?: boolean
  11 +}
  12 +
  13 +const Index = (props: Props) => {
  14 + const { value = [], onChange, edit } = props;
  15 + const [form] = Form.useForm();
  16 + const [visible, setVisible] = React.useState(false);
  17 + const [current, setCurrent] = React.useState({} as WashItem);
  18 +
  19 + const columns: ColumnsType<WashItem> = [
  20 + {
  21 + title: "适用门店",
  22 + dataIndex: "shopName",
  23 + key: "shopName",
  24 + align: "center",
  25 + },
  26 + {
  27 + title: "是否默认添加洗车项目",
  28 + dataIndex: "isWash",
  29 + key: "isWash",
  30 + align: "center",
  31 + render: (text: any, record: WashItem) => <div>{record.isWash == '1' ? '是' : '否'}</div>
  32 + },
  33 + {
  34 + title: "洗车项目",
  35 + dataIndex: "itemName",
  36 + key: "washName",
  37 + align: "center",
  38 + },
  39 + {
  40 + title: "操作",
  41 + align: "center",
  42 + render: (text: any, record: WashItem) => (
  43 + <div>
  44 + <Button
  45 + onClick={(e) => {
  46 + setCurrent(record);
  47 + setVisible(true);
  48 + }}
  49 + type="link"
  50 + disabled={!edit}
  51 + >
  52 + 编辑
  53 + </Button>
  54 + <Button
  55 + type="link"
  56 + danger
  57 + disabled={!edit}
  58 + style={{ marginLeft: 5 }}
  59 + onClick={() => {
  60 + const _list = value;
  61 + const partList = _list.filter((e) => e.itemId != record.itemId);
  62 + onChange && onChange([...partList]);
  63 + }}
  64 + >
  65 + 删除
  66 + </Button>
  67 + </div>
  68 + ),
  69 + },
  70 + ];
  71 +
  72 + const onSure = (data: WashItem, shopId?: number) => {
  73 + if (shopId) {
  74 + const _index = value.findIndex(e => e.shopId == shopId);
  75 + value[_index] = data;
  76 + onChange && onChange([...value]);
  77 + setVisible(false);
  78 + } else {
  79 + value.push(data);
  80 + onChange && onChange([...value]);
  81 + setVisible(false);
  82 + }
  83 + };
  84 +
  85 + return (
  86 + <div>
  87 + <Button
  88 + type="primary"
  89 + style={{ marginBottom: 10 }}
  90 + disabled={!edit}
  91 + onClick={() => {
  92 + setVisible(true);
  93 + setCurrent({} as WashItem);
  94 + }}
  95 + >
  96 + 新增
  97 + </Button>
  98 + <Form component={false} form={form}>
  99 + <Table
  100 + bordered
  101 + columns={columns}
  102 + dataSource={[...value]}
  103 + rowKey="shopId"
  104 + style={{ width: 700 }}
  105 + />
  106 + </Form>
  107 + <WashModal
  108 + value={current}
  109 + visible={visible}
  110 + onCancel={() => setVisible(false)}
  111 + onOk={onSure}
  112 + data={value}
  113 + />
  114 + </div>
  115 + );
  116 +};
  117 +
  118 +export default Index;
... ...
src/pages/cas/workOrder/base/components/WashModal.tsx 0 → 100644
  1 +import React, { useState, useEffect } from "react";
  2 +import { Modal, Table, Input, Select, Form, Radio, message } from 'antd';
  3 +import * as api from "../api";
  4 +import usePagination from "@/hooks/usePagination";
  5 +import Column from "antd/lib/table/Column";
  6 +import { debounce } from "lodash";
  7 +import { RowSelectionType } from "antd/es/table/interface";
  8 +import { getBrandFilterApi } from "@/common/api";
  9 +import useInitail from "@/hooks/useInitail";
  10 +import { getShopList } from "../../../MaintenanceCard/Upsert/api";
  11 +import * as IF from "../../../MaintenanceCard/Upsert/interface";
  12 +
  13 +const Search = Input.Search;
  14 +const { Option } = Select;
  15 +const FormItem = Form.Item;
  16 +
  17 +interface Props {
  18 + visible: boolean;
  19 + onCancel: () => any;
  20 + onOk: (data: api.WashItem, shopId?: number) => any;
  21 + value: api.WashItem;
  22 + data: api.WashItem[];
  23 +}
  24 +
  25 +const washData = [
  26 + {
  27 + itemId: 1,
  28 + itemName: "垃圾洗车",
  29 + },
  30 + {
  31 + itemId: 2,
  32 + itemName: "一般洗车",
  33 + },
  34 +];
  35 +
  36 +export default function ItemSelect(props: Props) {
  37 + const { visible, onCancel, onOk, value, data } = props;
  38 + const {data: shops} = useInitail(getShopList, [], undefined);
  39 + const [form] = Form.useForm();
  40 +
  41 + useEffect(() => {
  42 + if (value.itemId) {
  43 + form.setFieldsValue(
  44 + {...value, shop: {value: value.shopId, label: value.shopName}, item: {value: value.itemId, label: value.itemName}}
  45 + );
  46 + } else {
  47 + form.resetFields();
  48 + }
  49 + }, [visible]);
  50 +
  51 +function handleSave(_value: any) {
  52 + console.log("pppp", _value);
  53 + const _index = data.findIndex(e => e.shopId === _value.shop.value);
  54 + if (_index > -1 && !value.shopId) {
  55 + message.error('该门店已有洗车');
  56 + return;
  57 + }
  58 + onOk({
  59 + isWash: _value.isWash,
  60 + shopName: _value.shop.label,
  61 + shopId: _value.shop.value,
  62 + itemName: _value.item.label,
  63 + itemId: _value.item.value
  64 + }, value.shopId);
  65 +}
  66 +
  67 + return (
  68 + <Modal
  69 + visible={visible}
  70 + title="洗车"
  71 + width={700}
  72 + onCancel={() => onCancel()}
  73 + onOk={() => form.submit()}
  74 + >
  75 + <Form
  76 + form={form}
  77 + labelCol={{ span: 8 }}
  78 + wrapperCol={{ span: 18 }}
  79 + onFinish={handleSave}
  80 + >
  81 + <FormItem
  82 + name="shop"
  83 + label="适用门店"
  84 + rules={[{ required: true, message: "必填" }]}
  85 + >
  86 + <Select placeholder="请选择门店" labelInValue disabled={!!value.shopId}>
  87 + {shops.map((r) => (
  88 + <Select.Option key={r.id} value={r.id}>
  89 + {r.name || ""}
  90 + </Select.Option>
  91 + ))}
  92 + </Select>
  93 + </FormItem>
  94 + <FormItem
  95 + name="isWash"
  96 + label="是否默认添加洗车项目"
  97 + rules={[{ required: true, message: "必填" }]}
  98 + >
  99 + <Radio.Group>
  100 + <Radio value="1">是</Radio>
  101 + <Radio value="2">否</Radio>
  102 + </Radio.Group>
  103 + </FormItem>
  104 + <FormItem
  105 + name="item"
  106 + label="洗车项目"
  107 + rules={[{ required: true, message: "必填" }]}
  108 + >
  109 + <Select placeholder="请选择洗车项目" labelInValue>
  110 + {washData.map((r) => (
  111 + <Select.Option key={r.itemId} value={r.itemId}>
  112 + {r.itemName || ""}
  113 + </Select.Option>
  114 + ))}
  115 + </Select>
  116 + </FormItem>
  117 + </Form>
  118 + </Modal>
  119 + );
  120 +}
... ...
src/pages/cas/workOrder/base/index.tsx 0 → 100644
  1 +import useInitial from "@/hooks/useInitail";
  2 +import React, { useEffect, useState } from "react";
  3 +import * as API from "./api";
  4 +import { PageHeaderWrapper } from "@ant-design/pro-layout";
  5 +import {
  6 + Card,
  7 + Button,
  8 + InputNumber,
  9 + message,
  10 + Form,
  11 + Popconfirm,
  12 + Row,
  13 + DatePicker,
  14 +} from "antd";
  15 +import WashList from './components/WashList';
  16 +
  17 +const FormItem = Form.Item;
  18 +
  19 +const Basic = () => {
  20 + const [form] = Form.useForm();
  21 + const [edit, setEdit] = useState<boolean>(false);
  22 + const { data } = useInitial(API.fetchDetail, {}, "");
  23 + const [reset, setReset] = useState<boolean>(false);
  24 + const [visible, setVisible] = useState<boolean>(false)
  25 +
  26 + useEffect(() => {
  27 + form.setFieldsValue({ ...data });
  28 + setReset(false);
  29 + }, [data, reset]);
  30 +
  31 + function handleOk(feildValue: any) {
  32 + const param = {
  33 + ...feildValue,
  34 + id: data.id,
  35 + };
  36 + console.log('first', feildValue);
  37 + setEdit(false);
  38 + // API.saveApi(param)
  39 + // .then((res) => {
  40 + // setEdit(false);
  41 + // //setConfirmLoading(false);
  42 + // //setLoading(true);
  43 + // message.success("保存成功");
  44 + // })
  45 + // .catch((e) => {
  46 + // message.error(e.message);
  47 + // });
  48 + }
  49 +
  50 + function handleEdit() {
  51 + if (edit) {
  52 + setEdit(false);
  53 + } else {
  54 + setEdit(true);
  55 + }
  56 + }
  57 +
  58 + return (
  59 + <PageHeaderWrapper title="基础设置">
  60 + <Card>
  61 + <Form
  62 + form={form}
  63 + onFinish={handleOk}
  64 + onValuesChange={(changeValue, values) => {}}
  65 + >
  66 + <div
  67 + style={{ display: "flex", flexDirection: "row", flexWrap: "wrap" }}
  68 + >
  69 + <h2 style={{ width: "100%" }}>常规设置</h2>
  70 + <FormItem
  71 + label="客户订件金额要求"
  72 + name="morningShiftPercent"
  73 + rules={[{ required: true, message: "请输入客户订件金额要求" }]}
  74 + style={{ width: 500 }}
  75 + >
  76 + <InputNumber
  77 + disabled={!edit}
  78 + min={0}
  79 + formatter={(value) => `${value}%`}
  80 + parser={(value: any) => value.replace("%", "")}
  81 + style={{ width: 200 }}
  82 + />
  83 + </FormItem>
  84 + <FormItem
  85 + label="每月索赔复核待办起始日"
  86 + name="time"
  87 + rules={[
  88 + {
  89 + type: "object" as const,
  90 + required: true,
  91 + message: "请选择每月索赔复核待办起始日",
  92 + },
  93 + ]}
  94 + style={{ width: 500 }}
  95 + >
  96 + <DatePicker disabled={!edit} />
  97 + </FormItem>
  98 + <h2 style={{ width: "100%" }}>洗车设置</h2>
  99 + <FormItem
  100 + label="洗车列表"
  101 + rules={[
  102 + {
  103 + required: true,
  104 + min: 1,
  105 + message: "洗车列表不能为空",
  106 + type: "array",
  107 + },
  108 + ]}
  109 + shouldUpdate
  110 + name="partList"
  111 + >
  112 + <WashList edit={edit} />
  113 + </FormItem>
  114 + <Row style={{ width: "100%" }} justify="center">
  115 + {!edit ? (
  116 + <Button type="primary" onClick={handleEdit}>
  117 + 编辑
  118 + </Button>
  119 + ) : (
  120 + <div>
  121 + <Button type="primary" onClick={form.submit}>
  122 + 确定
  123 + </Button>
  124 + <Popconfirm
  125 + title="确定取消?取消将重置数据"
  126 + onConfirm={() => {
  127 + setReset(true);
  128 + setEdit(false);
  129 + }}
  130 + >
  131 + <Button style={{ marginLeft: 60 }}>取消</Button>
  132 + </Popconfirm>
  133 + </div>
  134 + )}
  135 + </Row>
  136 + </div>
  137 + </Form>
  138 + </Card>
  139 + </PageHeaderWrapper>
  140 + );
  141 +};
  142 +
  143 +export default Basic;
... ...
src/pages/cas/workOrder/washCar/api.ts 0 → 100644
  1 +import { http } from '@/typing/http';
  2 +import request from '@/utils/request';
  3 +import { CAS_HOST, OOP_HOST, PMS_HOST } from '@/utils/host';
  4 +
  5 +/** 作业项管理分页数据*/
  6 +export function getWorkControl(params: WorkProject.queryList): http.PromisePageResp<WorkProject.showUpdatedetails> {
  7 + return request.get(`${CAS_HOST}/erp/work/item/page`, { params });
  8 +}
... ...
src/pages/cas/workOrder/washCar/components/Modal.tsx 0 → 100644
  1 +import React, { useState, useEffect } from "react";
  2 +import "@ant-design/compatible/assets/index.css";
  3 +import {
  4 + Input,
  5 + Select,
  6 + InputNumber,
  7 + Modal,
  8 + Form,
  9 + Spin,
  10 +} from "antd";
  11 +import * as api from "../api";
  12 +import usePagination from "@/hooks/usePagination";
  13 +
  14 +const FormItem = Form.Item;
  15 +const { Option } = Select;
  16 +const maxFormProps = {
  17 + labelCol: { span: 5 },
  18 + wrapperCol: { span: 15 },
  19 +};
  20 +
  21 +interface Props {
  22 + item: any
  23 + visible: boolean;
  24 + setVisible: (value: boolean) => void
  25 +}
  26 +export default function SaveModal(props: Props) {
  27 + const [form] = Form.useForm();
  28 + const { item, visible, setVisible } = props;
  29 + const { loading, list } = usePagination(api.getWorkControl, { workType: 7, pageSize: 100 });
  30 + const [confirmLoading, setConfirmLoading] = useState<boolean>(false);
  31 +
  32 + useEffect(() => {
  33 + if (!item.id) {
  34 + console.log('item', item)
  35 + }
  36 + }, []);
  37 +
  38 + function save(fieldsValue: any) {
  39 + setConfirmLoading(true);
  40 + // const datas = {
  41 + // ...fieldsValue,
  42 + // id: item.id || undefined,
  43 + // brandId,
  44 + // stdType: 2,
  45 + // seriesId: fieldsValue.series === "2" ? fieldsValue.seriesId : undefined,
  46 + // specCodes:
  47 + // fieldsValue.vehicleCode === "2"
  48 + // ? list.map((e: any) => e.specCode)
  49 + // : undefined,
  50 + // };
  51 + // api
  52 + // .saveWorkProject(datas)
  53 + // .then(() => {
  54 + // message.success("操作成功!");
  55 + // fetchList();
  56 + // setConfirmLoading(false);
  57 + // onCancel();
  58 + // })
  59 + // .catch((e) => {
  60 + // setConfirmLoading(false);
  61 + // message.error(e.message);
  62 + // });
  63 + }
  64 +
  65 + return (
  66 + <Modal
  67 + title={item.id ? "新增" : "编辑"}
  68 + width={600}
  69 + visible={visible}
  70 + confirmLoading={confirmLoading}
  71 + onOk={() => form.submit()}
  72 + onCancel={() => {
  73 + setVisible(false);
  74 + }}
  75 + destroyOnClose
  76 + >
  77 + <Spin spinning={loading}>
  78 + <Form
  79 + form={form}
  80 + onFinish={save}
  81 + //onFieldsChange={(changedFields, allFields) => onChangeFile(changedFields, allFields)}
  82 + >
  83 + <FormItem
  84 + label="洗车项目"
  85 + name="workType"
  86 + rules={[{ required: true, message: "该选项为必选项" }]}
  87 + {...maxFormProps}
  88 + >
  89 + <Select
  90 + style={{ width: "100%" }}
  91 + placeholder="请选择"
  92 + disabled={!!item.id}
  93 + maxTagTextLength={20}
  94 + >
  95 + {list.map((e) => (
  96 + <Option key={e.id} value={e.id}>
  97 + {`${e.itemName}(${e.itemCode})`}
  98 + </Option>
  99 + ))}
  100 + </Select>
  101 + </FormItem>
  102 + <FormItem
  103 + label="金额"
  104 + name="money"
  105 + rules={[{ required: true, message: "该填写金额" }]}
  106 + {...maxFormProps}
  107 + >
  108 + <InputNumber style={{ width: 200 }} placeholder="请输入金额" />
  109 + </FormItem>
  110 + </Form>
  111 + </Spin>
  112 + </Modal>
  113 + );
  114 +}
... ...
src/pages/cas/workOrder/washCar/index.tsx 0 → 100644
  1 +import React, { useState } from "react";
  2 +import { PageHeaderWrapper } from "@ant-design/pro-layout";
  3 +import { Table, Card, Popconfirm, Divider, Button } from "antd";
  4 +import * as api from "./api";
  5 +import CreateModal from './components/Modal';
  6 +import usePagination from '@/hooks/usePagination';
  7 +
  8 +const Column = Table.Column;
  9 +
  10 +export default function WorkStationIndex() {
  11 + const [visible, setVisible] = useState(false);
  12 + const [item, setItem] = useState<any>({});
  13 +
  14 + const { loading, list, paginationConfig } = usePagination(api.getWorkControl, { workType: 7 });
  15 +
  16 + function handleDelete(param?: number) {
  17 + console.log('xxxxx');
  18 + }
  19 +
  20 + return (
  21 + <PageHeaderWrapper title="洗车项目配置">
  22 + <div
  23 + style={{
  24 + display: "flex",
  25 + flexDirection: "row",
  26 + justifyContent: "flex-start",
  27 + alignItems: "center",
  28 + marginBottom: 20,
  29 + }}
  30 + >
  31 + <Button type="primary" onClick={() => setVisible(true)}>
  32 + 新增
  33 + </Button>
  34 + </div>
  35 + <Card>
  36 + <Table
  37 + dataSource={list}
  38 + pagination={paginationConfig}
  39 + rowKey="id"
  40 + loading={loading}
  41 + >
  42 + <Column title="洗车项目" dataIndex="name" align="center" />
  43 + <Column title="价格" dataIndex="money" align="center" />
  44 + <Column
  45 + title="操作"
  46 + align="center"
  47 + render={(text, record: any) => (
  48 + <>
  49 + <a
  50 + onClick={(e) => {
  51 + e.preventDefault();
  52 + setItem(record);
  53 + setVisible(true);
  54 + }}
  55 + >
  56 + 编辑
  57 + </a>
  58 + <span>
  59 + <Divider type="vertical" />
  60 + <Popconfirm
  61 + title={`是否删除【${record.itemName}】?`}
  62 + onConfirm={() => handleDelete(record.id)}
  63 + okText="确定"
  64 + cancelText="取消"
  65 + >
  66 + <a
  67 + onClick={(e) => e.preventDefault()}
  68 + style={{ color: "red" }}
  69 + >
  70 + 删除
  71 + </a>
  72 + </Popconfirm>
  73 + </span>
  74 + </>
  75 + )}
  76 + />
  77 + </Table>
  78 + </Card>
  79 + <CreateModal item={item} visible={visible} setVisible={setVisible} />
  80 + </PageHeaderWrapper>
  81 + );
  82 +}
... ...
src/pages/contract/Canteen/api.ts
... ... @@ -32,9 +32,9 @@ export function saveApi(params: KtCanteenSpace.Item): http.PromiseResp&lt;void&gt; {
32 32 /**
33 33 * 查询可配置第三方
34 34 */
35   -export function getThirdPartyApi(): http.PromiseRespA<KtCanteenSpace.ThirdParty> {
36   - return request.get(`${CONTRACT_HOST}/erp/canteen/thirdparty/configurable/list`);
37   -}
  35 +// export function getThirdPartyApi(): http.PromiseRespA<KtCanteenSpace.ThirdParty> {
  36 +// return request.get(`${CONTRACT_HOST}/erp/canteen/thirdparty/configurable/list`);
  37 +// }
38 38  
39 39 /**
40 40 * 查询可配置服务门店
... ...
src/pages/contract/Canteen/components/SaveModal.tsx
1   -import React, { useState, useEffect } from 'react';
  1 +import React, { useState, useEffect } from "react";
2 2 import { Button, message, Modal, Select, Form, Input } from "antd";
3   -import { saveApi, getServiceShop, getThirdPartyApi } from "../api";
4   -import {EatMethodData, EatSummaryData, OperationModeData} from '@/pages/contract/entity';
5   -import PositionSelector from '@/components/PositionSelector';
6   -import useInitial from "@/hooks/useInitail";
7   -import ServiceShopModal from './ServiceShopModal';
  3 +import { saveApi, getServiceShop } from "../api";
  4 +import { OperationModeData } from "@/pages/contract/entity";
  5 +import PositionSelector from "@/components/PositionSelector";
  6 +import ServiceShopModal from "./ServiceShopModal";
8 7  
9 8 interface Props {
10   - item: KtCanteenSpace.Item,
11   - visible: boolean,
12   - onCancel: Function,
13   - fetchList: () => any
  9 + item: KtCanteenSpace.Item;
  10 + visible: boolean;
  11 + onCancel: Function;
  12 + fetchList: () => any;
14 13 }
15 14  
16 15 const formItemLayout = {
... ... @@ -27,9 +26,6 @@ const Item = Form.Item;
27 26 const Option = Select.Option;
28 27 export default function SaveModal(props: Props) {
29 28 const { visible, onCancel, fetchList, item = {} } = props;
30   - const {data: thirdPartys} = useInitial<KtCanteenSpace.ThirdParty[], object>(getThirdPartyApi, [], {});
31   - const [thirdParty, setThirdParty] = useState<KtCanteenSpace.ThirdParty>({});
32   - const [stmtShopId, setStmtShopId] = useState<number | undefined>();
33 29 const [serviceShops, setServiceShops] = useState<KtCanteenSpace.Shop[]>([]);
34 30 const [loading, setLoading] = useState(false);
35 31 const [form] = Form.useForm();
... ... @@ -38,31 +34,28 @@ export default function SaveModal(props: Props) {
38 34 if (visible) {
39 35 form.setFieldsValue({
40 36 ...item,
41   - stmtShopId: (item.stmtShop || {}).shopId,
42 37 address: {
43 38 address: item.address,
44 39 point: {
45 40 lng: item.addressLng,
46   - lat: item.addressLat
47   - }
48   - }
  41 + lat: item.addressLat,
  42 + },
  43 + },
49 44 });
50   - setStmtShopId((item.stmtShop || {}).shopId);
51   - setThirdParty(thirdPartys.find(i => i.id == item.thirdpartyId) || {});
52   - } else { form.resetFields(); }
  45 + } else {
  46 + form.resetFields();
  47 + }
53 48 }, [visible]);
54 49  
55   - console.log('111', item, thirdPartys, thirdParty);
56   -
57 50 useEffect(() => {
58   - if (stmtShopId && thirdParty.id) {
59   - getServiceShop({canteenId: item.id, stmtShopId, thirdpartyId: thirdParty.id}).then(res => {
  51 + getServiceShop({ canteenId: item.id })
  52 + .then((res) => {
60 53 setServiceShops(res.data || []);
61   - }).catch(e => {
  54 + })
  55 + .catch((e) => {
62 56 message.error(e.message);
63 57 });
64   - }
65   - }, [stmtShopId, thirdParty]);
  58 + }, []);
66 59  
67 60 function submit() {
68 61 form.validateFields().then((fields) => {
... ... @@ -72,20 +65,19 @@ export default function SaveModal(props: Props) {
72 65 address: fields.address.address,
73 66 addressLng: fields.address.point.lng,
74 67 addressLat: fields.address.point.lat,
75   - stmtShopId,
76   - thirdpartyId: thirdParty.id,
77   - thirdpartyName: thirdParty.shortName,
78 68 };
79 69 setLoading(true);
80   - saveApi(params).then(() => {
81   - message.success('保存成功');
82   - setLoading(false);
83   - fetchList();
84   - onCancel();
85   - }).catch((e: any) => {
86   - message.error(e.message);
87   - setLoading(false);
88   - });
  70 + saveApi(params)
  71 + .then(() => {
  72 + message.success("保存成功");
  73 + setLoading(false);
  74 + fetchList();
  75 + onCancel();
  76 + })
  77 + .catch((e: any) => {
  78 + message.error(e.message);
  79 + setLoading(false);
  80 + });
89 81 });
90 82 }
91 83  
... ... @@ -97,50 +89,31 @@ export default function SaveModal(props: Props) {
97 89 maskClosable={false}
98 90 onCancel={() => onCancel()}
99 91 footer={[
100   - <Button key="1" loading={loading} onClick={() => onCancel()}>取消</Button>,
101   - <Button key="2" type="primary" loading={loading} disabled={loading} onClick={() => submit()}>确认</Button>
  92 + <Button key="1" loading={loading} onClick={() => onCancel()}>
  93 + 取消
  94 + </Button>,
  95 + <Button key="2" type="primary" loading={loading} disabled={loading} onClick={() => submit()}>
  96 + 确认
  97 + </Button>,
102 98 ]}
103 99 >
104 100 <Form form={form} {...formItemLayout}>
105   - <Item label="食堂名称" name="name" required rules={[{ required: true, message: '请输入食堂名称' }]}>
  101 + <Item label="食堂名称" name="name" required rules={[{ required: true, message: "请输入食堂名称" }]}>
106 102 <Input maxLength={10} placeholder="请输入" />
107 103 </Item>
108   - <Item label="食堂地理位置" name="address" required rules={[{ required: true, message: '请输入食堂地理位置' }]}>
109   - <PositionSelector style={{ width: '100%' }} />
110   - </Item>
111   - <Item label="第三方" name="thirdpartyId" required rules={[{ required: true, message: '请选择第三方' }]}>
112   - <Select
113   - disabled={!!item.id}
114   - placeholder="请选择"
115   - onChange={(v: number) => {
116   - const thirdParty = thirdPartys.find(i => i.id == v) || {};
117   - setThirdParty(thirdParty);
118   - }}
119   - >
120   - {thirdPartys.map(i => (<Option value={i.id || -1} key={i.id || -1}>{i.shortName || ''}</Option>))}
121   - </Select>
  104 + <Item label="食堂地理位置" name="address" required rules={[{ required: true, message: "请输入食堂地理位置" }]}>
  105 + <PositionSelector style={{ width: "100%" }} />
122 106 </Item>
123   - <Item label="结算门店" name="stmtShopId" required rules={[{ required: true, message: '请选择结算门店' }]}>
124   - <Select disabled={!!item.id} placeholder="请选择" onChange={(v: number) => setStmtShopId(v)}>
125   - {(thirdParty.stmtShops || []).map(i => (<Option value={i.shopId || -1} key={i.shopId || -1}>{i.shopName || ''}</Option>))}
126   - </Select>
127   - </Item>
128   - <Item label="服务门店" name="serviceShops" required rules={[{ required: true, message: '请选择服务门店' }]}>
  107 + <Item label="服务门店" name="serviceShops" required rules={[{ required: true, message: "请选择服务门店" }]}>
129 108 <ServiceShopModal serviceShops={serviceShops} />
130 109 </Item>
131   - <Item label="就餐方式" name="repastWay" required rules={[{ required: true, message: '请选择食堂就餐方式' }]}>
132   - <Select placeholder="请选择">
133   - {EatMethodData.map(i => (<Option value={i.value} key={i.value}>{i.label || ''}</Option>))}
134   - </Select>
135   - </Item>
136   - <Item label="就餐统计" name="repastCountWay" required rules={[{ required: true, message: '请选择就餐统计' }]}>
137   - <Select placeholder="请选择">
138   - {EatSummaryData.map(i => (<Option value={i.value} key={i.value}>{i.label || ''}</Option>))}
139   - </Select>
140   - </Item>
141   - <Item label="运营方式" name="operationWay" required rules={[{ required: true, message: '请选择食堂运营方式' }]}>
  110 + <Item label="运营方式" name="operationWay" required rules={[{ required: true, message: "请选择食堂运营方式" }]}>
142 111 <Select placeholder="请选择">
143   - {OperationModeData.map(i => (<Option value={i.value} key={i.value}>{i.label || ''}</Option>))}
  112 + {OperationModeData.map((i) => (
  113 + <Option value={i.value} key={i.value}>
  114 + {i.label || ""}
  115 + </Option>
  116 + ))}
144 117 </Select>
145 118 </Item>
146 119 </Form>
... ...
src/pages/contract/Canteen/index.tsx
1 1 import React, { useState } from "react";
2 2 import { Button, Card, ConfigProvider, Divider, message, Popconfirm, Table } from "antd";
3   -import { PageHeaderWrapper } from '@ant-design/pro-layout';
  3 +import { PageHeaderWrapper } from "@ant-design/pro-layout";
4 4 import usePagination from "@/hooks/usePagination";
5   -import SaveModal from './components/SaveModal';
  5 +import SaveModal from "./components/SaveModal";
6 6 import DetailModal from "./components/DetailModal";
7   -import { getPageListApi, deleteApi } from './api';
8   -import st from './style.less';
  7 +import { getPageListApi, deleteApi } from "./api";
  8 +import st from "./style.less";
9 9 import zhCN from "antd/lib/locale-provider/zh_CN";
10   -import {EatMethod, EatSummary, OperationMode} from '@/pages/contract/entity';
  10 +import { OperationMode } from "@/pages/contract/entity";
11 11 import PriceSaveModal from "./components/PriceSaveModal";
12 12 import PriceTableModal from "./components/PriceTableModal";
13 13  
... ... @@ -22,20 +22,30 @@ export default function Index() {
22 22 const [visiblePriceShop, setVisiblePriceShop] = useState(false);
23 23  
24 24 function _delete(id?: number) {
25   - deleteApi(id).then(() => {
26   - message.success('操作成功');
27   - setParams({ current: 1 }, true);
28   - }).catch(e => {
29   - message.error(e.message);
30   - });
  25 + deleteApi(id)
  26 + .then(() => {
  27 + message.success("操作成功");
  28 + setParams({ current: 1 }, true);
  29 + })
  30 + .catch((e) => {
  31 + message.error(e.message);
  32 + });
31 33 }
32 34  
33 35 return (
34 36 <PageHeaderWrapper title="食堂配置">
35 37 <ConfigProvider locale={zhCN}>
36 38 <Card className={st.page}>
37   - <div style={{ display: 'flex', flexDirection: 'row', justifyContent: 'flex-end', marginBottom: 20 }}>
38   - <Button type="primary" onClick={() => { setVisible(true); setItem({}); }}>新增</Button>
  39 + <div style={{ display: "flex", flexDirection: "row", justifyContent: "flex-end", marginBottom: 20 }}>
  40 + <Button
  41 + type="primary"
  42 + onClick={() => {
  43 + setVisible(true);
  44 + setItem({});
  45 + }}
  46 + >
  47 + 新增
  48 + </Button>
39 49 </div>
40 50 <Table
41 51 size="small"
... ... @@ -45,18 +55,14 @@ export default function Index() {
45 55 rowKey={(item: KtCanteenSpace.Item) => `${item.id}`}
46 56 onChange={(_pagination) => setParams({ ..._pagination }, true)}
47 57 >
48   - <Column title="食堂" dataIndex="name" width="10%" align="center" />
49   - <Column title="食堂地址" dataIndex="address" width="10%" align="center" />
50   - <Column title="第三方" dataIndex="thirdpartyName" width="10%" align="center" />
51   - <Column title="就餐方式" dataIndex="repastWay" width="10%" align="center" render={(t, _: KtCanteenSpace.Item) => EatMethod[_.repastWay || 0]} />
52   - <Column title="就餐统计" dataIndex="repastCountWay" width="10%" align="center" render={(t, _: KtCanteenSpace.Item) => EatSummary[_.repastCountWay || 0]} />
53   - <Column title="运营方式" dataIndex="operationWay" width="10%" align="center" render={(t, _: KtCanteenSpace.Item) => OperationMode[_.operationWay || 0]} />
  58 + <Column title="食堂" dataIndex="name" width="15%" align="center" />
  59 + <Column title="食堂地址" dataIndex="address" width="20%" align="center" />
54 60 <Column
55   - title="结算门店"
56   - dataIndex="stmtShop"
  61 + title="运营方式"
  62 + dataIndex="operationWay"
57 63 width="10%"
58 64 align="center"
59   - render={(text, _item: KtCanteenSpace.Item) => ((_item.stmtShop || {}).shopName || '')}
  65 + render={(t, _: KtCanteenSpace.Item) => OperationMode[_.operationWay || 0]}
60 66 />
61 67 <Column
62 68 title="服务门店"
... ... @@ -69,30 +75,68 @@ export default function Index() {
69 75 setVisibleShop(true);
70 76 setShops(_item.serviceShops || []);
71 77 }}
72   - style={{ color: '#4189FD' }}
  78 + style={{ color: "#4189FD" }}
73 79 >
74 80 查看
75 81 </a>
76 82 )}
77 83 />
78 84 <Column
79   - title="操作"
  85 + title="下载"
80 86 align="center"
81 87 render={(text, _item: KtCanteenSpace.Item) => (
82 88 <span>
83   - <a onClick={() => { setVisible(true); setItem(_item); }}>编辑</a>
  89 + <a title="点击下载二维码" href={`/api/file/download?fid=${_item.wxQrCodeFid}`}>
  90 + 客户就餐码
  91 + </a>
84 92 <Divider type="vertical" />
85   - <a onClick={() => { setVisiblePriceShop(true); setItem(_item); }}>查看价格</a>
  93 + <a title="点击下载二维码" href={`/api/file/download?fid=${_item.appQrCodeFid}`}>
  94 + 员工就餐码
  95 + </a>
  96 + </span>
  97 + )}
  98 + />
  99 + <Column
  100 + title="操作"
  101 + align="center"
  102 + render={(text, _item: KtCanteenSpace.Item) => (
  103 + <span>
  104 + <a
  105 + onClick={() => {
  106 + setVisible(true);
  107 + setItem(_item);
  108 + }}
  109 + >
  110 + 编辑
  111 + </a>
86 112 <Divider type="vertical" />
87   - <a onClick={() => { setVisiblePrice(true); setItem(_item); }}>调整价格</a>
  113 + <a
  114 + onClick={() => {
  115 + setVisiblePriceShop(true);
  116 + setItem(_item);
  117 + }}
  118 + >
  119 + 查看价格
  120 + </a>
88 121 <Divider type="vertical" />
89   - <Popconfirm
90   - title="是否删除?"
91   - onConfirm={() => _delete(_item.id)}
92   - okText="确定"
93   - cancelText="取消"
  122 + <a
  123 + onClick={() => {
  124 + setVisiblePrice(true);
  125 + setItem(_item);
  126 + }}
94 127 >
95   - <a onClick={(e) => { e.preventDefault(); }} style={{ color: 'red' }}>删除</a>
  128 + 调整价格
  129 + </a>
  130 + <Divider type="vertical" />
  131 + <Popconfirm title="是否删除?" onConfirm={() => _delete(_item.id)} okText="确定" cancelText="取消">
  132 + <a
  133 + onClick={(e) => {
  134 + e.preventDefault();
  135 + }}
  136 + style={{ color: "red" }}
  137 + >
  138 + 删除
  139 + </a>
96 140 </Popconfirm>
97 141 </span>
98 142 )}
... ... @@ -105,22 +149,14 @@ export default function Index() {
105 149 onCancel={() => setVisiblePrice(false)}
106 150 fetchList={() => setParams({ current: 1 }, true)}
107 151 />
108   - <PriceTableModal
109   - visible={visiblePriceShop}
110   - item={item}
111   - onCancel={() => setVisiblePriceShop(false)}
112   - />
  152 + <PriceTableModal visible={visiblePriceShop} item={item} onCancel={() => setVisiblePriceShop(false)} />
113 153 <SaveModal
114 154 visible={visible}
115 155 item={item}
116 156 onCancel={() => setVisible(false)}
117 157 fetchList={() => setParams({ current: 1 }, true)}
118 158 />
119   - <DetailModal
120   - visible={visibleShop}
121   - shops={shops}
122   - onCancel={() => setVisibleShop(false)}
123   - />
  159 + <DetailModal visible={visibleShop} shops={shops} onCancel={() => setVisibleShop(false)} />
124 160 </ConfigProvider>
125 161 </PageHeaderWrapper>
126 162 );
... ...
src/pages/contract/Canteen/interface.d.ts
... ... @@ -14,20 +14,16 @@ declare namespace KtCanteenSpace {
14 14 * 列表项
15 15 */
16 16 interface Item {
17   - id?: number, // 食堂id
18   - name?: string, // 食堂名称
19   - address?: string, // 食堂位置
20   - addressLng?: number, // 食堂位置经度
21   - addressLat?: number, // 食堂位置纬度
22   - thirdpartyId?: number, // 第三方id
23   - thirdpartyName?: string, // 第三方名称
24   - repastWay?: number, // 就餐方式,1送餐制、2就餐制
25   - repastCountWay?: number, // 就餐统计方式,1按员工确认、2按排班表
26   - operationWay?: number, // 运营方式,1自营、2承包
27   - stmtShop?: Shop, // 结算门店
28   - stmtShopId?: number, // 结算门店id,不可编辑
29   - serviceShops?: ServiceShop[], // 服务门店
30   - canConfigPrice?: boolean, // 是否可配置价格
  17 + id?: number; // 食堂id
  18 + name?: string; // 食堂名称
  19 + address?: string; // 食堂位置
  20 + addressLng?: number; // 食堂位置经度
  21 + addressLat?: number; // 食堂位置纬度
  22 + operationWay?: number; // 运营方式,1自营、2承包
  23 + serviceShops?: ServiceShop[]; // 服务门店
  24 + canConfigPrice?: boolean; // 是否可配置价格
  25 + wxQrCodeFid?: string;
  26 + appQrCodeFid?: string;
31 27 }
32 28  
33 29 /**
... ...
src/pages/dalaran/Account/components/EditModal.tsx
... ... @@ -34,6 +34,8 @@ export default function EditModal({
34 34 );
35 35 const [saveLoading, setSaveLoading] = useState<boolean>(false);
36 36  
  37 + // 存储平台类型
  38 + const [platformType, setPlatFormType] = useState<number>(-1);
37 39 useEffect(() => {
38 40 if (visible) {
39 41 form.setFieldsValue({
... ... @@ -48,9 +50,21 @@ export default function EditModal({
48 50 : undefined,
49 51 });
50 52 }
  53 + return () => {
  54 + setPlatFormType(-1);
  55 + };
51 56 }, [visible]);
52 57  
53 58 async function handleSave(values: any) {
  59 + if (platformType === 1) {
  60 + let re = /^[a-zA-Z]/;
  61 + const _account: string = values.account;
  62 + let myArray = re.test(_account);
  63 + if (!myArray) {
  64 + message.error("请输入字母开头的快手号", 3);
  65 + return;
  66 + }
  67 + }
54 68 setSaveLoading(true);
55 69 const _accountParams: AccountDTO = {
56 70 id: record?.id,
... ... @@ -61,7 +75,7 @@ export default function EditModal({
61 75 userId: values?.user?.value,
62 76 userName: values?.user?.label,
63 77 accountType: values.accountType,
64   - playbackSearchKey: values.playbackSearchKey,
  78 + // playbackSearchKey: values.playbackSearchKey,
65 79 };
66 80 try {
67 81 const { result, success } = await saveAccount(_accountParams);
... ... @@ -102,18 +116,11 @@ export default function EditModal({
102 116 wrapperCol={{ span: 15 }}
103 117 >
104 118 <FormItem
105   - name="account"
106   - label="账号"
107   - rules={[{ required: true, message: "请输入账号" }]}
108   - >
109   - <Input placeholder="请输入账号" disabled={!!record?.affirm} />
110   - </FormItem>
111   - <FormItem
112 119 name="type"
113 120 label="平台类型"
114 121 rules={[{ required: true, message: "请选择平台类型" }]}
115 122 >
116   - <Select placeholder="请选择平台类型">
  123 + <Select placeholder="请选择平台类型" onChange={(value) => setPlatFormType(value)}>
117 124 {[1, 2, 3, 4].map((type) => (
118 125 <Select.Option value={type} key={type}>
119 126 {PlatformEnum[type]}
... ... @@ -121,22 +128,16 @@ export default function EditModal({
121 128 ))}
122 129 </Select>
123 130 </FormItem>
124   - <Form.Item
125   - noStyle
126   - shouldUpdate={(prevValues, currentValues) => prevValues.type !== currentValues.type}
  131 + <FormItem
  132 + name="account"
  133 + label="账号"
  134 + rules={[{ required: true, message: platformType === 1 ? "请输入快手号" : "请输入账号" }, { pattern: platformType === 1 ? /^[a-zA-Z]/ : undefined, message: "请输入字母开头的快手号" }]}
  135 +
127 136 >
128   - {({ getFieldValue }) => {
129   - //获取输入账号,账号数字开头展示关键词输入框
130   - const _account = form.getFieldValue("account");
131   - const re = /^[0-9].*/;
132   - const _res = re.test(_account);
133   - return (getFieldValue('type') === 1 && _res ? (
134   - <Form.Item name="playbackSearchKey" label="直播搜索关键词">
135   - <Input />
136   - </Form.Item>
137   - ) : null);
138   - }}
139