Просмотр исходного кода

展馆和课程-新增加功能

shaogen1995 недель назад: 3
Родитель
Сommit
54088f2e51

Разница между файлами не показана из-за своего большого размера
+ 3593 - 0
后台管理/src/pages/A6record/A6add/data.ts


+ 37 - 0
后台管理/src/pages/A6record/A6add/index.module.scss

@@ -0,0 +1,37 @@
+.A6add {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+    .ant-modal {
+      width: 1120px !important;
+    }
+    .ant-modal-body {
+      border-top: 1px solid #ccc;
+      padding-top: 15px !important;
+
+      .FormBox {
+        width: 100%;
+        display: flex;
+        flex-wrap: wrap;
+        .ant-form-item {
+          width: 48%;
+          .ant-row {
+            // display: flex;
+            .ant-form-item-label {
+              width: 110px;
+            }
+            .ant-picker,
+            .ant-input-number {
+              width: 100%;
+            }
+          }
+        }
+      }
+    }
+    .FormBtn {
+      margin-top: 24px;
+      text-align: center;
+    }
+  }
+}

+ 196 - 0
后台管理/src/pages/A6record/A6add/index.tsx

@@ -0,0 +1,196 @@
+import React, { useCallback, useEffect } from 'react'
+import styles from './index.module.scss'
+import {
+  Button,
+  Cascader,
+  DatePicker,
+  Form,
+  Input,
+  InputNumber,
+  Modal,
+  Select,
+  TimePicker
+} from 'antd'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import { useDispatch, useSelector } from 'react-redux'
+import { RootState } from '@/store'
+import dayjs from 'dayjs'
+import { A3_APIgetList } from '@/store/action/A3course'
+import { cityArr, papersSelArr, statusSelArr } from './data'
+import TextArea from 'antd/es/input/TextArea'
+import { A6_APIadd } from '@/store/action/A6record'
+import { MessageFu } from '@/utils/message'
+
+type Props = {
+  closeFu: () => void
+  upTableFu: () => void
+}
+
+function A6add({ closeFu, upTableFu }: Props) {
+  const dispatch = useDispatch()
+  useEffect(() => {
+    dispatch(A3_APIgetList({ pageNum: 1, pageSize: 99999 }))
+  }, [dispatch])
+
+  // 预约课程
+  const { list: subjectNameArr } = useSelector(
+    (state: RootState) => state.A3course.tableInfo
+  )
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {}, [])
+
+  //  通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      const obj = {
+        ...values,
+        bookDate: dayjs(values.bookDate).format('YYYY-MM-DD'),
+        bookTime: `${dayjs(values.bookTime[0]).format('HH:mm')}-${dayjs(
+          values.bookTime[1]
+        ).format('HH:mm')}`,
+        createTime: dayjs(values.createTime).format('YYYY-MM-DD HH:mm:ss'),
+        pcsStudent: values.pcsStudent || 0
+      }
+      if (values.myCity && values.myCity.length > 1) {
+        obj.province = values.myCity[0]
+        obj.city = values.myCity[1]
+      }
+      // console.log(12465, obj)
+
+      const res = await A6_APIadd(obj)
+      if (res.code === 0) {
+        MessageFu.success('新增成功')
+        upTableFu()
+        closeFu()
+      }
+    },
+    [closeFu, upTableFu]
+  )
+
+  return (
+    <Modal
+      wrapClassName={styles.A6add}
+      open={true}
+      title='新增课程预约记录'
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <Form
+        name='basic'
+        onFinish={onFinish}
+        onFinishFailed={onFinishFailed}
+        autoComplete='off'
+        scrollToFirstError
+        initialValues={{
+          myCity: ['广东省', '横琴粤澳深度合作区'],
+          status: 1
+        }}
+      >
+        <div className='FormBox'>
+          <Form.Item
+            label='预约日期'
+            name='bookDate'
+            rules={[{ required: true, message: '请选择' }]}
+          >
+            <DatePicker placeholder='请选择' />
+          </Form.Item>
+
+          <Form.Item
+            label='预约时段'
+            name='bookTime'
+            rules={[{ required: true, message: '请选择' }]}
+          >
+            <TimePicker.RangePicker format='HH:mm' />
+          </Form.Item>
+
+          <Form.Item
+            label='预约课程'
+            name='subjectName'
+            rules={[{ required: true, message: '请选择' }]}
+          >
+            <Select
+              allowClear
+              placeholder='请选择'
+              options={subjectNameArr.map(v => ({ label: v.name, value: v.name }))}
+            />
+          </Form.Item>
+
+          <Form.Item
+            label='负责人姓名'
+            name='name'
+            getValueFromEvent={e => e.target.value.trim()}
+          >
+            <Input placeholder='请输入' maxLength={50} showCount />
+          </Form.Item>
+
+          <Form.Item
+            label='联系方式'
+            name='phone'
+            getValueFromEvent={e => e.target.value.trim()}
+          >
+            <Input placeholder='请输入' maxLength={50} showCount />
+          </Form.Item>
+
+          <Form.Item label='来自地区' name='myCity'>
+            <Cascader options={cityArr} placeholder='请选择' />
+          </Form.Item>
+
+          <Form.Item label='证件类型' name='papers'>
+            <Select allowClear placeholder='请选择' options={papersSelArr} />
+          </Form.Item>
+
+          <Form.Item label='证件号码' name='identity'>
+            <Input placeholder='请输入' maxLength={50} showCount />
+          </Form.Item>
+
+          <Form.Item label='参观学生人数' name='pcsStudent'>
+            <InputNumber min={0} max={999} precision={0} placeholder='请输入数字' />
+          </Form.Item>
+
+          <Form.Item label='随堂老师人数' name='pcsTeacher'>
+            <InputNumber min={0} max={999} precision={0} placeholder='请输入数字' />
+          </Form.Item>
+
+          <Form.Item
+            label='所属机构'
+            name='unit'
+            getValueFromEvent={e => e.target.value.trim()}
+          >
+            <TextArea placeholder='请输入' maxLength={200} showCount />
+          </Form.Item>
+
+          <Form.Item label='团队描述' name='remark'>
+            <TextArea maxLength={200} placeholder='请输入' showCount />
+          </Form.Item>
+
+          <Form.Item label='审核状态' name='status'>
+            <Select placeholder='请选择' options={statusSelArr} />
+          </Form.Item>
+
+          <Form.Item
+            label='申请时间'
+            name='createTime'
+            rules={[{ required: true, message: '请选择' }]}
+          >
+            <DatePicker showTime format='YYYY-MM-DD HH:mm:ss' />
+          </Form.Item>
+        </div>
+
+        {/* 确定和取消按钮 */}
+        <Form.Item className='FormBtn'>
+          <Button type='primary' htmlType='submit'>
+            提交
+          </Button>
+          &emsp;
+          <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+        </Form.Item>
+      </Form>
+    </Modal>
+  )
+}
+
+const MemoA6add = React.memo(A6add)
+
+export default MemoA6add

+ 11 - 0
后台管理/src/pages/A6record/index.tsx

@@ -11,6 +11,7 @@ import MyTable from '@/components/MyTable'
 import { A6tableC } from '@/utils/tableData'
 import A6auth from './A6auth'
 import LocStat from './LocStat'
+import A6add from './A6add'
 
 const { RangePicker } = DatePicker
 
@@ -130,6 +131,9 @@ function A6record() {
   // 点击地区统计
   const [locShow, setLocShow] = useState(false)
 
+  // 点击新增
+  const [addShow, setAddShow] = useState(false)
+
   return (
     <div className={styles.A6record}>
       <div className='pageTitle'>课程预约记录</div>
@@ -153,6 +157,10 @@ function A6record() {
           </div>
         </div>
         <div className='A6top1'>
+          <Button type='primary' onClick={() => setAddShow(true)}>
+            新增
+          </Button>
+          &emsp;
           <Button onClick={() => setLocShow(true)}>地区统计</Button>&emsp;
           <Button onClick={resetSelectFu}>重置</Button>
         </div>
@@ -185,6 +193,9 @@ function A6record() {
       {locShow ? (
         <LocStat type='课程' apiObj={fromData} closeFu={() => setLocShow(false)} />
       ) : null}
+
+      {/* 点击新增 */}
+      {addShow ? <A6add closeFu={() => setAddShow(false)} upTableFu={getListFu} /> : null}
     </div>
   )
 }

+ 25 - 0
后台管理/src/pages/B2exhiLog/B2add/data.ts

@@ -0,0 +1,25 @@
+export const B2typeSelArr = [
+  { value: 'person', label: '个人预约' },
+  { value: 'team', label: '团队预约' }
+]
+
+export const B2statusSelArr = [
+  { value: 1, label: '已核销' },
+  { value: 0, label: '未核销' }
+]
+
+export type B2renListType = {
+  id: number
+  name: string
+  phone: string
+  papers: string
+  identity: string
+}
+
+export const B2baseRenData: B2renListType = {
+  id: 1,
+  name: '',
+  phone: '',
+  papers: '',
+  identity: ''
+}

+ 68 - 0
后台管理/src/pages/B2exhiLog/B2add/index.module.scss

@@ -0,0 +1,68 @@
+.B2add {
+  :global {
+    .ant-modal-close {
+      display: none;
+    }
+    .ant-modal {
+      width: 1420px !important;
+      top: 50px !important;
+    }
+    .ant-modal-body {
+      border-top: 1px solid #ccc;
+      padding-top: 15px !important;
+
+      .FormBox {
+        width: 100%;
+        padding-right: 20px;
+        max-height: 650px;
+        overflow: auto;
+        display: flex;
+        flex-wrap: wrap;
+        .ant-form-item {
+          width: 48%;
+          .ant-row {
+            // display: flex;
+            .ant-form-item-label {
+              width: 110px;
+            }
+            .ant-picker,
+            .ant-input-number {
+              width: 100%;
+            }
+          }
+        }
+        .antdRowAll {
+          width: 96%;
+        }
+
+        .B2Form {
+          width: 100%;
+          display: flex;
+          align-items: center;
+          .B2Formll {
+            width: 110px;
+            text-align: right;
+            span {
+              color: #ff4d4f;
+            }
+          }
+          .B2Formrr {
+            width: calc(100% - 110px);
+            .B2FormErr {
+              font-size: 14px;
+              color: #999;
+            }
+            .ant-table-cell {
+              text-align: center;
+              padding: 8px;
+            }
+          }
+        }
+      }
+    }
+    .FormBtn {
+      margin-top: 24px;
+      text-align: center;
+    }
+  }
+}

+ 326 - 0
后台管理/src/pages/B2exhiLog/B2add/index.tsx

@@ -0,0 +1,326 @@
+import React, { useCallback, useMemo, useState } from 'react'
+import styles from './index.module.scss'
+import {
+  Button,
+  Cascader,
+  DatePicker,
+  Form,
+  Input,
+  InputNumber,
+  Modal,
+  Select,
+  TimePicker
+} from 'antd'
+import dayjs from 'dayjs'
+import { B2baseRenData, B2renListType, B2statusSelArr, B2typeSelArr } from './data'
+import { cityArr, papersSelArr } from '@/pages/A6record/A6add/data'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import TextArea from 'antd/es/input/TextArea'
+import MyTable from '@/components/MyTable'
+import { MessageFu } from '@/utils/message'
+import { B2_APIadd } from '@/store/action/B2exhiLog'
+
+type Props = {
+  closeFu: () => void
+  upTableFu: () => void
+}
+
+function B2add({ closeFu, upTableFu }: Props) {
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {}, [])
+
+  // 个人和团队预约
+  const [type, setType] = useState('person')
+
+  // 参观人/负责人信息
+  const [renList, setRenList] = useState<B2renListType[]>([{ ...B2baseRenData }])
+
+  //  通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      let renArr = [] as B2renListType[]
+      if (type === 'person') renArr = [...renList]
+      else renArr = [renList[0]]
+
+      const obj: any = {
+        teamDesc: values.teamDesc,
+        teamPcs: values.teamPcs,
+        type
+      }
+      obj.info = []
+      let infoTemp: any = {
+        createTime: dayjs(values.createTime).format('YYYY-MM-DD HH:mm:ss'),
+        updateTime: dayjs(values.updateTime).format('YYYY-MM-DD HH:mm:ss'),
+        bookDate: dayjs(values.bookDate).format('YYYY-MM-DD'),
+        time: `${dayjs(values.time[0]).format('HH:mm')}-${dayjs(values.time[1]).format(
+          'HH:mm'
+        )}`,
+        status: values.status
+      }
+      if (values.myCity && values.myCity.length > 1) {
+        infoTemp.province = values.myCity[0]
+        infoTemp.city = values.myCity[1]
+      }
+      renArr.forEach(v => {
+        infoTemp = {
+          ...infoTemp,
+          name: v.name,
+          phone: v.phone,
+          papers: v.papers,
+          identity: v.identity
+        }
+        obj.info.push(infoTemp)
+      })
+
+      const res = await B2_APIadd(obj)
+      if (res.code === 0) {
+        MessageFu.success('新增成功')
+        upTableFu()
+        closeFu()
+      }
+    },
+    [closeFu, renList, type, upTableFu]
+  )
+
+  const txtChange = useCallback(
+    (id: number, value: string, key: 'name' | 'phone' | 'papers' | 'identity') => {
+      setRenList(
+        renList.map(v => ({
+          ...v,
+          [key]: id === v.id ? value : v[key]
+        }))
+      )
+    },
+    [renList]
+  )
+
+  const txtCss = useCallback(
+    (flag: boolean) => {
+      const flagRes = flag || type === 'person'
+      const css: any = {
+        opacity: flagRes ? '1' : '0.5',
+        pointerEvents: flagRes ? 'auto' : 'none'
+      }
+      return css
+    },
+    [type]
+  )
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: `${type === 'team' ? '负责人' : '参观人'}姓名`,
+        render: (item: B2renListType, _: any, index: number) => (
+          <Input
+            style={txtCss(index === 0)}
+            placeholder='请输入'
+            maxLength={20}
+            showCount
+            value={item.name}
+            onChange={e => txtChange(item.id, e.target.value.trim(), 'name')}
+          />
+        )
+      },
+      {
+        title: `${type === 'team' ? '负责人' : '参观人'}电话`,
+        render: (item: B2renListType, _: any, index: number) => (
+          <Input
+            style={txtCss(index === 0)}
+            placeholder='请输入'
+            maxLength={20}
+            showCount
+            value={item.phone}
+            onChange={e => txtChange(item.id, e.target.value.trim(), 'phone')}
+          />
+        )
+      },
+      {
+        title: '证件类型',
+        render: (item: B2renListType, _: any, index: number) => (
+          <Select
+            style={{ ...txtCss(index === 0), width: '100%' }}
+            placeholder='请选择'
+            options={papersSelArr}
+            value={item.papers || null}
+            onChange={e => txtChange(item.id, e, 'papers')}
+          />
+        )
+      },
+      {
+        title: '证件号码',
+        render: (item: B2renListType, _: any, index: number) => (
+          <Input
+            style={txtCss(index === 0)}
+            placeholder='请输入'
+            maxLength={20}
+            showCount
+            value={item.identity}
+            onChange={e => txtChange(item.id, e.target.value.trim(), 'identity')}
+          />
+        )
+      },
+
+      {
+        title: '操作',
+        render: (item: B2renListType, _: any, index: number) =>
+          index === 0 || type === 'team' ? (
+            ' - '
+          ) : (
+            <MyPopconfirm
+              txtK='删除'
+              onConfirm={() => setRenList(renList.filter(v => v.id !== item.id))}
+            />
+          )
+      }
+    ]
+  }, [renList, txtChange, txtCss, type])
+
+  return (
+    <Modal
+      wrapClassName={styles.B2add}
+      open={true}
+      title='新增展馆预约记录'
+      footer={
+        [] // 设置footer为空,去掉 取消 确定默认按钮
+      }
+    >
+      <Form
+        name='basic'
+        onFinish={onFinish}
+        onFinishFailed={onFinishFailed}
+        autoComplete='off'
+        scrollToFirstError
+        initialValues={{
+          myCity: ['广东省', '横琴粤澳深度合作区'],
+          type: 'person',
+          status: 1
+        }}
+      >
+        <div className='FormBox'>
+          <Form.Item
+            label='申请时间'
+            name='createTime'
+            rules={[{ required: true, message: '请选择' }]}
+          >
+            <DatePicker showTime format='YYYY-MM-DD HH:mm:ss' />
+          </Form.Item>
+
+          <Form.Item
+            label='预约类型'
+            name='type'
+            rules={[{ required: true, message: '请选择' }]}
+          >
+            <Select
+              placeholder='请选择'
+              value={type}
+              onChange={e => setType(e)}
+              options={B2typeSelArr}
+            />
+          </Form.Item>
+
+          <Form.Item label='来自地区' name='myCity'>
+            <Cascader options={cityArr} placeholder='请选择' />
+          </Form.Item>
+
+          <Form.Item
+            label='预约日期'
+            name='bookDate'
+            rules={[{ required: true, message: '请选择' }]}
+          >
+            <DatePicker placeholder='请选择' />
+          </Form.Item>
+
+          <Form.Item
+            label='预约时段'
+            name='time'
+            rules={[{ required: true, message: '请选择' }]}
+          >
+            <TimePicker.RangePicker format='HH:mm' />
+          </Form.Item>
+
+          <Form.Item
+            label='核销状态'
+            name='status'
+            rules={[{ required: true, message: '请选择' }]}
+          >
+            <Select placeholder='请选择' options={B2statusSelArr} />
+          </Form.Item>
+
+          <Form.Item
+            label='核销时间'
+            name='updateTime'
+            rules={[{ required: true, message: '请选择' }]}
+          >
+            <DatePicker showTime format='YYYY-MM-DD HH:mm:ss' />
+          </Form.Item>
+          {type === 'team' ? (
+            <>
+              <Form.Item
+                label='参团人数'
+                name='teamPcs'
+                rules={[{ required: true, message: '请输入参团人数!' }]}
+              >
+                <InputNumber min={1} max={999} precision={0} placeholder='请输入数字' />
+              </Form.Item>
+
+              <Form.Item label='团队描述' name='teamDesc' className='antdRowAll'>
+                <TextArea
+                  autoSize
+                  maxLength={200}
+                  placeholder='请输入内容,不超过200个字'
+                />
+              </Form.Item>
+            </>
+          ) : null}
+
+          <div className='B2Form'>
+            <div className='B2Formll'>
+              <span>* </span>
+              {type === 'team' ? '负责人' : '参观人'}信息:
+            </div>
+            <div className='B2Formrr'>
+              <Button
+                disabled={type === 'team'}
+                type='primary'
+                onClick={() => {
+                  if (renList.length >= 10) return MessageFu.warning('最多添加10条信息')
+                  setRenList([...renList, { ...B2baseRenData, id: Date.now() }])
+                }}
+              >
+                新增
+              </Button>
+              &emsp;
+              <span className='B2FormErr'>
+                预约类型为团队预约的时候,只取第一条数据为负责人信息
+              </span>
+            </div>
+          </div>
+
+          <div className='B2Form'>
+            <div className='B2Formll'></div>
+            <div className='B2Formrr'>
+              <MyTable
+                list={renList}
+                pagingInfo={false}
+                columnsTemp={[]}
+                lastBtn={tableLastBtn}
+              />
+            </div>
+          </div>
+        </div>
+        {/* 确定和取消按钮 */}
+        <Form.Item className='FormBtn'>
+          <Button type='primary' htmlType='submit'>
+            提交
+          </Button>
+          &emsp;
+          <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+        </Form.Item>
+      </Form>
+    </Modal>
+  )
+}
+
+const MemoB2add = React.memo(B2add)
+
+export default MemoB2add

+ 3 - 3
后台管理/src/pages/B2exhiLog/B2look.tsx

@@ -71,17 +71,17 @@ function B2look({ sId, closeFu }: Props) {
               <div className='B2boxll'>
                 {info.type === 'person' ? '参观人' : '负责人'}姓名:
               </div>
-              <div className='B2boxrr'>{item.name}</div>
+              <div className='B2boxrr'>{item.name || '-'}</div>
             </div>
             <div className='B2box'>
               <div className='B2boxll'>
                 {info.type === 'person' ? '参观人' : '负责人'}电话:
               </div>
-              <div className='B2boxrr'>{item.phone}</div>
+              <div className='B2boxrr'>{item.phone || '-'}</div>
             </div>
             <div className='B2box'>
               <div className='B2boxll B2boxllZZ'>
-                {item.papers || '证件号码'}:<span>{item.identity}</span>
+                {item.papers || '证件号码'}:<span>{item.identity || '-'}</span>
               </div>
             </div>
           </div>

+ 11 - 0
后台管理/src/pages/B2exhiLog/index.tsx

@@ -21,6 +21,7 @@ import LocStat from '../A6record/LocStat'
 import ExportJsonExcel from 'js-export-excel'
 import dayjs from 'dayjs'
 import { domShowFu } from '@/utils/domShow'
+import B2add from './B2add'
 
 const { RangePicker } = DatePicker
 
@@ -235,6 +236,9 @@ function B2exhiLog() {
     })
   }, [fromData])
 
+  // 点击新增
+  const [addShow, setAddShow] = useState(false)
+
   return (
     <div className={styles.B2exhiLog}>
       <div className='pageTitle'>展馆预约记录</div>
@@ -267,6 +271,10 @@ function B2exhiLog() {
           </div>
         </div>
         <div className='B2top1'>
+          <Button type='primary' onClick={() => setAddShow(true)}>
+            新增
+          </Button>
+          &emsp;
           <Button onClick={deriveFu}>导出</Button>&emsp;
           <Button onClick={() => setLocShow(true)}>地区统计</Button>&emsp;
           <Button onClick={resetSelectFu}>重置</Button>
@@ -294,6 +302,9 @@ function B2exhiLog() {
       {locShow ? (
         <LocStat type='展馆' apiObj={fromData} closeFu={() => setLocShow(false)} />
       ) : null}
+
+      {/* 点击新增 */}
+      {addShow ? <B2add closeFu={() => setAddShow(false)} upTableFu={getListFu} /> : null}
     </div>
   )
 }

+ 5 - 0
后台管理/src/store/action/A2orderSetNew.ts

@@ -20,6 +20,11 @@ export const A2N_APIgetList = (time?: string, isList?: boolean): any => {
   }
 }
 
+// 给课程预约记录-手动自己新增数据用
+export const A2N_APIgetTimeList = () => {
+  return http.get(`cms/subjectBook/list`)
+}
+
 /**
  * 课程预约设置-新版-详情
  */

+ 7 - 0
后台管理/src/store/action/A6record.ts

@@ -53,3 +53,10 @@ export const Loc_APIlist = (data: any, type: '课程' | '展馆') => {
 export const A6_APIgetNumAll = (data: any) => {
   return http.post('cms/apply/count', data)
 }
+
+/**
+ * 课程预约记录-新增
+ */
+export const A6_APIadd = (data: any) => {
+  return http.post('cms/apply/subject/apply', data)
+}

+ 7 - 0
后台管理/src/store/action/B2exhiLog.ts

@@ -74,3 +74,10 @@ export const B2_APIgetInfo = (id: number) => {
 export const B2_APIgetNumAll = (data: any) => {
   return http.post('cms/applyExhibition/count', data)
 }
+
+/**
+ * 展馆预约记录-新增
+ */
+export const B2_APIadd = (data: any) => {
+  return http.post('cms/applyExhibition/apply', data)
+}

+ 2 - 2
后台管理/src/utils/http.ts

@@ -7,8 +7,8 @@ import { domShowFu } from './domShow'
 
 const envFlag = process.env.NODE_ENV === 'development'
 
-const baseUrlTemp = 'https://sit-hqbooking.4dage.com' // 测试环境
-// const baseUrlTemp = 'http://192.168.20.61:8091' // 线下环境
+// const baseUrlTemp = 'https://sit-hqbooking.4dage.com' // 测试环境
+const baseUrlTemp = 'http://192.168.20.61:8091' // 线下环境
 
 const baseFlag = baseUrlTemp.includes('https://')