shaogen1995 10 mēneši atpakaļ
vecāks
revīzija
d4b65ba91c

+ 102 - 0
src/pages/A4video/A4add/index.module.scss

@@ -0,0 +1,102 @@
+.A4add {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 12;
+  background-color: #fff;
+  border-radius: 10px;
+  padding: 24px;
+
+  :global {
+    .A4aMain {
+      width: 100%;
+      height: 100%;
+      overflow-y: auto;
+
+      textarea {
+        min-height: 150px !important;
+      }
+      .A4Text {
+        textarea {
+          min-height: 75px !important;
+        }
+      }
+
+      .A4fromRow {
+        position: relative;
+        width: 800px;
+
+        .A4_6Frow {
+          position: absolute;
+          left: 200px;
+          top: 5px;
+          color: #999;
+          font-size: 12px;
+        }
+      }
+
+      .ant-form {
+        width: 800px;
+
+        // .ant-input-affix-wrapper{
+        //   width: 800px;
+        // }
+        .formRow {
+          display: flex;
+
+          .formLeft {
+            position: relative;
+            width: 100px;
+            text-align: right;
+
+            & > span {
+              color: #ff4d4f;
+            }
+          }
+
+          .formRight {
+            width: calc(100% - 100px);
+          }
+        }
+
+        .A4abtn {
+          position: absolute;
+          z-index: 10;
+          left: 1200px;
+          top: 50%;
+          transform: translateY(-50%);
+        }
+      }
+    }
+
+    // 从查看进入
+    .A4aMainLook {
+      // 左边的 label 也不让选中
+      label {
+        pointer-events: none;
+      }
+
+      .ant-picker {
+        pointer-events: none;
+      }
+
+      .ant-checkbox-wrapper {
+        pointer-events: none;
+      }
+
+      .ant-input-number {
+        pointer-events: none;
+      }
+
+      .ant-select {
+        pointer-events: none;
+      }
+
+      .ant-radio-wrapper {
+        pointer-events: none;
+      }
+    }
+  }
+}

+ 222 - 0
src/pages/A4video/A4add/index.tsx

@@ -0,0 +1,222 @@
+import React, { useCallback, useEffect, useRef, useState } from 'react'
+import styles from './index.module.scss'
+import { A1EditInfoType } from '@/pages/A1goods/data'
+import { Button, Form, FormInstance, Input, InputNumber } from 'antd'
+import { A4_APIgetInfo, A4_APIsave } from '@/store/action/A4video'
+import { MessageFu } from '@/utils/message'
+import classNames from 'classnames'
+import ZupOne from '@/components/ZupOne'
+import TextArea from 'antd/es/input/TextArea'
+import MyPopconfirm from '@/components/MyPopconfirm'
+
+type Props = {
+  editInfo: A1EditInfoType
+  closeFu: () => void
+  addTableFu: () => void
+  editTableFu: () => void
+}
+
+function A4add({ editInfo, closeFu, addTableFu, editTableFu }: Props) {
+  // 表单的ref
+  const FormBoxRef = useRef<FormInstance>(null)
+
+  // 封面图的ref
+  const ZupThumbRef = useRef<any>(null)
+
+  // 附件的ref
+  const ZupVideoRef = useRef<any>(null)
+
+  // 编辑/查看 进入页面 获取信息
+  const getInfoFu = useCallback(async (id: number) => {
+    const res = await A4_APIgetInfo(id)
+    if (res.code === 0) {
+      const info = res.data
+      const obj = {
+        ...info
+      }
+
+      FormBoxRef.current?.setFieldsValue(obj)
+
+      // 设置封面图
+      ZupThumbRef.current?.setFileComFileFu({
+        fileName: '',
+        filePath: info.thumb
+      })
+
+      // 设置附件
+      ZupVideoRef.current?.setFileComFileFu({
+        fileName: info.fileName,
+        filePath: info.filePath
+      })
+    }
+  }, [])
+
+  // 附件 是否 已经点击过确定
+  const [fileCheck, setFileCheck] = useState(false)
+
+  useEffect(() => {
+    if (editInfo.id > 0) {
+      getInfoFu(editInfo.id)
+    } else {
+      FormBoxRef.current?.setFieldsValue({
+        sort: 999
+      })
+    }
+  }, [editInfo.id, getInfoFu])
+
+  // 没有通过校验
+  const onFinishFailed = useCallback(() => {
+    setFileCheck(true)
+  }, [])
+
+  //  通过校验点击确定
+  const onFinish = useCallback(
+    async (values: any) => {
+      setFileCheck(true)
+      const coverUrl1 = ZupThumbRef.current?.fileComFileResFu()
+      // 没有传 封面图
+      if (!coverUrl1.filePath) return
+
+      // 没有传视频附件
+      let fileName = ''
+      let filePath = ''
+      // txt附件
+      const ZupVideoRefObj = ZupVideoRef.current?.fileComFileResFu()
+      fileName = ZupVideoRefObj.fileName
+      filePath = ZupVideoRefObj.filePath
+      if (!filePath) return MessageFu.warning('请上传附件!')
+
+      const obj = {
+        ...values,
+        id: editInfo.id > 0 ? editInfo.id : null,
+        thumb: coverUrl1.filePath,
+        fileName,
+        filePath
+      }
+
+      const res = await A4_APIsave(obj)
+
+      if (res.code === 0) {
+        MessageFu.success(editInfo.txt + '成功!')
+        editInfo.id > 0 ? editTableFu() : addTableFu()
+        closeFu()
+      }
+    },
+    [addTableFu, closeFu, editInfo.id, editInfo.txt, editTableFu]
+  )
+
+  return (
+    <div className={styles.A4add}>
+      <div className={classNames('A4aMain', editInfo.txt === '查看' ? 'A4aMainLook' : '')}>
+        <Form
+          ref={FormBoxRef}
+          name='basic'
+          labelCol={{ span: 3 }}
+          onFinish={onFinish}
+          onFinishFailed={onFinishFailed}
+          autoComplete='off'
+          scrollToFirstError
+        >
+          <Form.Item label='名称' name='name' rules={[{ required: true, message: '请输入名称!' }]}>
+            <Input
+              readOnly={editInfo.txt === '查看'}
+              placeholder='请输入内容'
+              maxLength={20}
+              showCount
+            />
+          </Form.Item>
+
+          {/* 封面 */}
+          <div className='formRow'>
+            <div className='formLeft'>
+              <span>* </span>
+              封面:
+            </div>
+            <div className='formRight'>
+              <ZupOne
+                ref={ZupThumbRef}
+                isLook={editInfo.txt === '查看'}
+                fileCheck={fileCheck}
+                size={5}
+                dirCode={'A2video'}
+                myUrl='cms/video/upload'
+                format={['image/jpeg', 'image/png']}
+                formatTxt='png、jpg和jpeg'
+                checkTxt='请上传封面图!'
+                upTxt='最多1张'
+                myType='thumb'
+              />
+            </div>
+          </div>
+          {editInfo.txt === '查看' ? <br /> : null}
+
+          {/* 附件 */}
+          <div className='formRow'>
+            <div className='formLeft'>
+              <span>* </span>
+              附件:
+            </div>
+            <div className='formRight'>
+              <ZupOne
+                ref={ZupVideoRef}
+                isLook={editInfo.txt === '查看'}
+                fileCheck={fileCheck}
+                size={200}
+                dirCode='A2video'
+                myUrl='cms/video/upload'
+                format={['video/mp4']}
+                formatTxt='mp4'
+                checkTxt='请上传mp4附件!'
+                upTxt='最多1个'
+                myType='video'
+              />
+            </div>
+          </div>
+          {editInfo.txt === '查看' ? <br /> : null}
+
+          <Form.Item label='简介' name='remark'>
+            <TextArea
+              readOnly={editInfo.txt === '查看'}
+              maxLength={200}
+              showCount
+              placeholder='请输入内容'
+            />
+          </Form.Item>
+
+          <div className='A4fromRow'>
+            <Form.Item
+              label='排序值'
+              name='sort'
+              rules={[{ required: true, message: '请输入排序值!' }]}
+            >
+              <InputNumber min={1} max={999} precision={0} placeholder='请输入' />
+            </Form.Item>
+            <div className='A4_6Frow' hidden={editInfo.txt === '查看'}>
+              请输入1~999的数字。数字越小,排序越靠前。数字相同时,更新发布的内容排在前面
+            </div>
+          </div>
+
+          {/* 确定和取消按钮 */}
+          <Form.Item className='A4abtn'>
+            {editInfo.txt === '查看' ? (
+              <Button onClick={closeFu}>返回</Button>
+            ) : (
+              <>
+                <Button type='primary' htmlType='submit'>
+                  提交
+                </Button>
+                <br />
+                <br />
+                <MyPopconfirm txtK='取消' onConfirm={closeFu} />
+              </>
+            )}
+          </Form.Item>
+        </Form>
+      </div>
+    </div>
+  )
+}
+
+const MemoA4add = React.memo(A4add)
+
+export default MemoA4add

+ 26 - 0
src/pages/A4video/index.module.scss

@@ -1,4 +1,30 @@
 .A4video {
+  position: relative;
   :global {
+    .A4top {
+      border-radius: 10px;
+      background-color: #fff;
+      padding: 15px 24px;
+      display: flex;
+      justify-content: space-between;
+      & > div {
+        display: flex;
+        .A4TopRow {
+          display: flex;
+          align-items: center;
+          margin-right: 20px;
+          .ant-select-selection-placeholder {
+            color: black;
+          }
+        }
+      }
+    }
+    .A4tableBox {
+      border-radius: 10px;
+      overflow: hidden;
+      margin-top: 15px;
+      height: calc(100% - 77px);
+      background-color: #fff;
+    }
   }
 }

+ 139 - 2
src/pages/A4video/index.tsx

@@ -1,9 +1,146 @@
-import React from 'react'
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
 import styles from './index.module.scss'
+import { useDispatch, useSelector } from 'react-redux'
+import { RootState } from '@/store'
+import { MessageFu } from '@/utils/message'
+import { A1tableType } from '@/types'
+import { Button, Input } from 'antd'
+import MyPopconfirm from '@/components/MyPopconfirm'
+import MyTable from '@/components/MyTable'
+import { A4tableC } from '@/utils/tableData'
+import { A2FromDataType } from '../A2panorama/data'
+import { A4_APIdel, A4_APIgetList } from '@/store/action/A4video'
+import { A1EditInfoType } from '../A1goods/data'
+import A4add from './A4add'
+
+const fromDataBase: A2FromDataType = {
+  searchKey: '',
+  pageNum: 1,
+  pageSize: 10
+}
+
 function A4video() {
+  const dispatch = useDispatch()
+
+  const [fromData, setFromData] = useState(fromDataBase)
+
+  const getListFu = useCallback(() => {
+    dispatch(A4_APIgetList(fromData))
+  }, [dispatch, fromData])
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  const [inputKey, setInputKey] = useState(1)
+
+  // 输入框的输入
+  const timeRef = useRef(-1)
+  const txtChangeFu = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>, key: 'searchKey') => {
+      clearTimeout(timeRef.current)
+      timeRef.current = window.setTimeout(() => {
+        setFromData({ ...fromData, [key]: e.target.value.replaceAll("'", ''), pageNum: 1 })
+      }, 500)
+    },
+    [fromData]
+  )
+
+  // 点击重置
+  const resetSelectFu = useCallback(() => {
+    setInputKey(Date.now())
+    setFromData({ ...fromDataBase })
+  }, [])
+
+  const tableInfo = useSelector((state: RootState) => state.A4video.tableInfo)
+
+  const delTableFu = useCallback(
+    async (id: number) => {
+      const res = await A4_APIdel(id)
+      if (res.code === 0) {
+        MessageFu.success('删除成功!')
+        getListFu()
+      }
+    },
+    [getListFu]
+  )
+
+  const tableLastBtn = useMemo(() => {
+    return [
+      {
+        title: '操作',
+        render: (item: A1tableType) => (
+          <>
+            <Button
+              size='small'
+              type='text'
+              onClick={() => setEditInfo({ id: item.id, txt: '编辑' })}
+            >
+              编辑
+            </Button>
+
+            <MyPopconfirm txtK='删除' onConfirm={() => delTableFu(item.id)} />
+          </>
+        )
+      }
+    ]
+  }, [delTableFu])
+
+  //查看、新增、编辑
+  const [editInfo, setEditInfo] = useState<A1EditInfoType>({
+    id: 0,
+    txt: ''
+  })
+
   return (
     <div className={styles.A4video}>
-      <h1>A4video</h1>
+      <div className='pageTitle'>珍贵视频 {editInfo.id ? ` - ${editInfo.txt}` : ''}</div>
+
+      {/* 顶部筛选 */}
+      <div className='A4top'>
+        <div>
+          <div className='A4TopRow'>
+            <span>搜索:</span>
+            <Input
+              key={inputKey}
+              maxLength={20}
+              style={{ width: 200 }}
+              placeholder='请输入名称'
+              allowClear
+              onChange={e => txtChangeFu(e, 'searchKey')}
+            />
+          </div>
+        </div>
+        <div>
+          <Button onClick={resetSelectFu}>重置</Button>&emsp;
+          <Button type='primary' onClick={() => setEditInfo({ id: -1, txt: '新增' })}>
+            新增
+          </Button>
+        </div>
+      </div>
+
+      {/* 表格主体 */}
+      <div className='A4tableBox'>
+        <MyTable
+          yHeight={625}
+          list={tableInfo.list}
+          columnsTemp={A4tableC}
+          lastBtn={tableLastBtn}
+          pageNum={fromData.pageNum}
+          pageSize={fromData.pageSize}
+          total={tableInfo.total}
+          onChange={(pageNum, pageSize) => setFromData({ ...fromData, pageNum, pageSize })}
+        />
+      </div>
+
+      {editInfo.id ? (
+        <A4add
+          editInfo={editInfo}
+          closeFu={() => setEditInfo({} as A1EditInfoType)}
+          addTableFu={resetSelectFu}
+          editTableFu={getListFu}
+        />
+      ) : null}
     </div>
   )
 }

+ 39 - 0
src/store/action/A4video.ts

@@ -0,0 +1,39 @@
+import http from '@/utils/http'
+import { AppDispatch } from '..'
+
+/**
+ *珍贵视频-列表
+ */
+
+export const A4_APIgetList = (data: any): any => {
+  return async (dispatch: AppDispatch) => {
+    const res = await http.post('cms/video/pageList', data)
+    if (res.code === 0) {
+      const obj = {
+        list: res.data.records,
+        total: res.data.total
+      }
+      dispatch({ type: 'A4/getList', payload: obj })
+    }
+  }
+}
+/**
+ * 珍贵视频-删除
+ */
+export const A4_APIdel = (id: number) => {
+  return http.get(`cms/video/remove/${id}`)
+}
+
+/**
+ * 珍贵视频-获取详情
+ */
+export const A4_APIgetInfo = (id: number) => {
+  return http.get(`cms/video/detail/${id}`)
+}
+
+/**
+ * 珍贵视频-新增、编辑
+ */
+export const A4_APIsave = (data: any) => {
+  return http.post('cms/video/save', data)
+}

+ 28 - 0
src/store/reducer/A4video.ts

@@ -0,0 +1,28 @@
+import { A4tableType } from '@/types'
+
+// 初始化状态
+const initState = {
+  // 列表数据
+  tableInfo: {
+    list: [] as A4tableType[],
+    total: 0
+  }
+}
+
+// 定义 action 类型
+type Props = {
+  type: 'A4/getList'
+  payload: { list: A4tableType[]; total: number }
+}
+
+// reducer
+export default function Reducer(state = initState, action: Props) {
+  switch (action.type) {
+    // 获取列表数据
+    case 'A4/getList':
+      return { ...state, tableInfo: action.payload }
+
+    default:
+      return state
+  }
+}

+ 2 - 0
src/store/reducer/index.ts

@@ -5,6 +5,7 @@ import { combineReducers } from 'redux'
 import A0Layout from './layout'
 import A1goods from './A1goods'
 import A2panorama from './A2panorama'
+import A4video from './A4video'
 import Z1user from './Z1user'
 import Z2log from './Z2log'
 
@@ -13,6 +14,7 @@ const rootReducer = combineReducers({
   A0Layout,
   A1goods,
   A2panorama,
+  A4video,
   Z1user,
   Z2log
 })

+ 1 - 0
src/types/api/A4video.ts

@@ -0,0 +1 @@
+export type A4tableType = any

+ 1 - 0
src/types/index.d.ts

@@ -1,5 +1,6 @@
 export * from './api/layot'
 export * from './api/A1goods'
 export * from './api/A2panorama'
+export * from './api/A4video'
 export * from './api/Z1user'
 export * from './api/Z2log'

+ 6 - 0
src/utils/tableData.ts

@@ -29,6 +29,12 @@ export const A2tableC = [
   ['text', '场景链接', 'link', 50, 'A'],
   ['txt', '排序值', 'sort']
 ]
+export const A4tableC = [
+  ['txt', '名称', 'name'],
+  ['img', '封面', 'thumb'],
+  ['text', '简介', 'remark', 50],
+  ['txt', '排序值', 'sort']
+]
 
 export const Z1tableC = [
   ['txt', '用户名', 'userName'],