diff --git a/web/client/src/components/setup.jsx b/web/client/src/components/setup.jsx index 41d8792..ce0a719 100644 --- a/web/client/src/components/setup.jsx +++ b/web/client/src/components/setup.jsx @@ -5,12 +5,13 @@ import { Checkbox, } from "@douyinfe/semi-ui"; -function Setup (props) { +function Setup(props) { const { close, tableType, tableList, - length + length, + objWidth } = props; const [check, setCheck] = useState([]); @@ -22,7 +23,7 @@ function Setup (props) { setCheck(checkItem ? JSON.parse(checkItem) : []) ischeck(); }, []); - function ischeck (value) { + function ischeck(value) { if (check.length >= length) { if (check.includes(value)) { return false; @@ -57,7 +58,7 @@ function Setup (props) { } visible={true} - style={{ width: 600 }} + style={{ width: objWidth?.modalWidth || 600 }} onOk={() => { localStorage.setItem(tableType, JSON.stringify(check)); close(); @@ -82,7 +83,7 @@ function Setup (props) {
{item.title}
-
+
{item.list?.map((itm) => { return ( { + const { dispatch, actions } = props + const { } = actions; + const [keywordTarget, setKeywordTarget] = useState('contractNo'); + const [keyword, setKeyword] = useState('');//搜索内容 + const [limits, setLimits] = useState()//每页实际条数 + const [query, setQuery] = useState({ limit: 10, page: 0 }); //页码信息 + const [tableData, setTableData] = useState([]); + const [importModalV, setImportModalV] = useState(false); - const columns = [ - { - title: '序号', - dataIndex: 'index', - render: (text, record, index) => index + 1 - }, - ]; - const data = []; + const [setup, setSetup] = useState(false);//表格设置是否显现 + const [setupp, setSetupp] = useState([]);//实际显示的表格列表 + const CONTRACTDETAILS = "contractDetails"; + const renderColumns = (columnKeys) => { + let columns = []; + Object.keys(columnKeys).map(key => { + tableList[0].list.push({ name: columnKeys[key], value: key }); + switch (key) { + default: + columns.push({ + title: columnKeys[key], dataIndex: key, key: key, + render: (text, record) => text === 0 ? text : text ? text : '—', width: 32 + columnKeys[key].length * 16 + }); + break; + } + }) + return columns; + } + const tableList = [{ + title: '基础信息', + list: [] + }]; + const columns = renderColumns(contractDetailsColumnKeys); + function seachValueChange(value) { + setKeyword(value) + } + useEffect(() => { + localStorage.getItem(CONTRACTDETAILS) == null + ? localStorage.setItem( + CONTRACTDETAILS, + JSON.stringify(['a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a10', 'a11', 'a12', 'a13', 'a14', 'a15', 'a16']) + ) + : ""; + attribute(); + }, []); + //获取表格属性设置 + function attribute() { + const arr = localStorage.getItem(CONTRACTDETAILS) + ? JSON.parse(localStorage.getItem(CONTRACTDETAILS)) + : []; + let newColumns = []; + for (let i = 0; i < columns.length; i++) { + if (arr.indexOf(columns[i].key) > -1) { + newColumns.push(columns[i]); + } + } + setSetupp(newColumns); + } + useEffect(() => { + + }, [query]) + function handleRow(record, index) {// 给偶数行设置斑马纹 + if (index % 2 === 0) { + return { + style: { + background: '#FAFCFF', + } + }; + } else { + return {}; + } + } + const scroll = useMemo(() => ({}), []); return ( <>
@@ -23,11 +91,116 @@ const ContractDetails = (props) => {
/
合同明细表
-
- - +
+
+
+
+
合同明细表
+
CONTRACT DETAILS
+
+
+
+
+
+
+ +
+
+ } + showClear + placeholder='请输入关键词搜索' + value={keyword} + style={{ width: 346 }} + onChange={seachValueChange}> + +
+ +
+
+ setSetup(true)} + /> +
{ setImportModalV(true); }}> + 导入 +
+
+ 导出全部 +
+
+
+
+ +
s)} + dataSource={tableData} + bordered={false} + empty="暂无数据" + pagination={false} + + onRow={handleRow} + scroll={scroll} + /> + +
+
+
+
+ + 共{limits}条信息 + + { + setQuery({ limit: pageSize, page: currentPage - 1 }); + page.current = currentPage - 1 + }} + /> +
+
+ + + + { + importModalV ? { + setImportModalV(false); + }} /> : '' + } + {setup ? ( + { + setSetup(false); + attribute(); + }} + /> + ) : ( + "" + )} ) } diff --git a/web/client/src/sections/business/containers/performanceReport/importContractDetailsModal.js b/web/client/src/sections/business/containers/performanceReport/importContractDetailsModal.js new file mode 100644 index 0000000..a3b22c9 --- /dev/null +++ b/web/client/src/sections/business/containers/performanceReport/importContractDetailsModal.js @@ -0,0 +1,175 @@ +'use strict'; +import React, { useState, useEffect } from 'react'; +import { connect } from 'react-redux'; +import { Modal, Form, Button, Notification } from '@douyinfe/semi-ui'; +import { IconUpload } from '@douyinfe/semi-icons'; +import XLSX from 'xlsx'; +import { contractDetailsColumnKeys } from '../../constants/index'; +//下载模板和上传文件读取 +const ImportContractDetailsModal = props => { + const { dispatch, actions, onCancel } = props; + const { humanAffairs } = actions; + const [msg, setMsg] = useState(''); + const [loading, setLoading] = useState(''); + const [postData, setPostData] = useState([]); + //初始化 + useEffect(() => { + }, []); + + const confirm = () => { + if (postData.length) { + setLoading(true) + // dispatch(humanAffairs.addSalesMemberBulk(postData)).then(res => { + // if (res.success) { + // onCancel() + // } + // setLoading(false) + // }) + } else { + Notification.warning({ content: '没有数据可以提交,请上传数据文件', duration: 2 }) + } + } + + const dldCsvMb = () => { + //表头 + let head = []; + Object.keys(contractDetailsColumnKeys).map(key => { + head.push(contractDetailsColumnKeys[key]); + }) + head = head.join(',') + "\n"; + //数据 + //let data = 1 + ',' + 2 + ',' + 3 + ',' + 4 + ',' + 5 + let templateCsv = "data:text/csv;charset=utf-8,\ufeff" + head; + //创建一个a标签 + let link = document.createElement("a"); + //为a标签设置属性 + link.setAttribute("href", templateCsv); + link.setAttribute("download", "合同明细表导入模板.csv"); + //点击a标签 + link.click(); + } + const download = () => { + dldCsvMb(); + } + + const fileLimit = '.csv'; + + const getFileBlob = (url) => { + return new Promise((resolve, reject) => { + let request = new XMLHttpRequest() + request.open("GET", url, true) + request.responseType = "blob" + request.onreadystatechange = e => { + if (request.readyState == 4) { + if (request.status == 200) { + if (window.FileReader) { + let reader = new FileReader(); + reader.readAsBinaryString(request.response); + reader.onload = event => { + try { + const { result } = event.target; + // 以二进制流方式读取得到整份excel表格对象 + const workbook = XLSX.read(result, { + type: "binary", + cellDates: true,//设为true,将天数的时间戳转为时间格式 + codepage: 936//解决了乱码问题 + }); + let data = []; // 存储获取到的数据 + // 遍历每张工作表进行读取(这里默认只读取第一张表) + for (const sheet in workbook.Sheets) { + if (workbook.Sheets.hasOwnProperty(sheet)) { + data = data.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet])); + } + } + resolve(data);//导出数据 + } catch (e) { + reject("失败"); + } + } + } + } + } + } + request.send(); + }) + } + + + const judgeNull = (value) => { + return value ? String(value).trim().replace(/\s*/g, "") : null; + } + + return ( + { + setMsg('') + setLoading(false) + setPostData([]) + onCancel() + }} + > +
+
+ { + setMsg(''); + setPostData([]); + }} + customRequest={(data) => { + const { file, onSuccess, onError } = data + getFileBlob(file.url).then(res => { + const error = (msg) => { + setMsg(msg) + onError({ message: msg }) + } + if (res.length > 1000) { + error('一次性上传数据行数应小于1000行,请分批上传') + return + } + if (!res.length) { + error('请填写至少一行数据') + return + } + let postData = []; + for (let i = 0; i < res.length; i++) { + let d = res[i]; + let obj = {}; + Object.keys(contractDetailsColumnKeys).map(key => { + obj[key] = d[contractDetailsColumnKeys[key]] || ''; + }) + postData.push(obj); + } + setPostData(postData) + let msg = '文件解析完成,点击确定按钮上传保存!' + setMsg(msg) + onSuccess({ message: msg }) + }) + }}> + + + {msg} +
最大不超过200M,导入文件需与 + download()} style={{ cursor: 'pointer', color: '#0066FF' }}>导入模板 + 一致
+ +
+ ) +} + +function mapStateToProps(state) { + const { auth, global } = state; + return { + user: auth.user, + actions: global.actions, + } +} + +export default connect(mapStateToProps)(ImportContractDetailsModal); \ No newline at end of file diff --git a/web/client/src/sections/business/containers/performanceReport/importInvoicingDetailsModal.js b/web/client/src/sections/business/containers/performanceReport/importInvoicingDetailsModal.js new file mode 100644 index 0000000..cba870b --- /dev/null +++ b/web/client/src/sections/business/containers/performanceReport/importInvoicingDetailsModal.js @@ -0,0 +1,175 @@ +'use strict'; +import React, { useState, useEffect } from 'react'; +import { connect } from 'react-redux'; +import { Modal, Form, Button, Notification } from '@douyinfe/semi-ui'; +import { IconUpload } from '@douyinfe/semi-icons'; +import XLSX from 'xlsx'; +import { invoicingDetailsColumnKeys } from '../../constants/index'; +//下载模板和上传文件读取 +const ImportInvoicingDetailsModal = props => { + const { dispatch, actions, onCancel } = props; + const { humanAffairs } = actions; + const [msg, setMsg] = useState(''); + const [loading, setLoading] = useState(''); + const [postData, setPostData] = useState([]); + //初始化 + useEffect(() => { + }, []); + + const confirm = () => { + if (postData.length) { + setLoading(true) + dispatch(humanAffairs.addSalesMemberBulk(postData)).then(res => { + if (res.success) { + onCancel() + } + setLoading(false) + }) + } else { + Notification.warning({ content: '没有数据可以提交,请上传数据文件', duration: 2 }) + } + } + + const dldCsvMb = () => { + //表头 + let head = []; + Object.keys(invoicingDetailsColumnKeys).map(key => { + head.push(invoicingDetailsColumnKeys[key]); + }) + head = head.join(',') + "\n"; + //数据 + //let data = 1 + ',' + 2 + ',' + 3 + ',' + 4 + ',' + 5 + let templateCsv = "data:text/csv;charset=utf-8,\ufeff" + head; + //创建一个a标签 + let link = document.createElement("a"); + //为a标签设置属性 + link.setAttribute("href", templateCsv); + link.setAttribute("download", "开票明细表导入模板.csv"); + //点击a标签 + link.click(); + } + const download = () => { + dldCsvMb(); + } + + const fileLimit = '.csv'; + + const getFileBlob = (url) => { + return new Promise((resolve, reject) => { + let request = new XMLHttpRequest() + request.open("GET", url, true) + request.responseType = "blob" + request.onreadystatechange = e => { + if (request.readyState == 4) { + if (request.status == 200) { + if (window.FileReader) { + let reader = new FileReader(); + reader.readAsBinaryString(request.response); + reader.onload = event => { + try { + const { result } = event.target; + // 以二进制流方式读取得到整份excel表格对象 + const workbook = XLSX.read(result, { + type: "binary", + cellDates: true,//设为true,将天数的时间戳转为时间格式 + codepage: 936//解决了乱码问题 + }); + let data = []; // 存储获取到的数据 + // 遍历每张工作表进行读取(这里默认只读取第一张表) + for (const sheet in workbook.Sheets) { + if (workbook.Sheets.hasOwnProperty(sheet)) { + data = data.concat(XLSX.utils.sheet_to_json(workbook.Sheets[sheet])); + } + } + resolve(data);//导出数据 + } catch (e) { + reject("失败"); + } + } + } + } + } + } + request.send(); + }) + } + + + const judgeNull = (value) => { + return value ? String(value).trim().replace(/\s*/g, "") : null; + } + + return ( + { + setMsg('') + setLoading(false) + setPostData([]) + onCancel() + }} + > +
+
+ { + setMsg(''); + setPostData([]); + }} + customRequest={(data) => { + const { file, onSuccess, onError } = data + getFileBlob(file.url).then(res => { + const error = (msg) => { + setMsg(msg) + onError({ message: msg }) + } + if (res.length > 1000) { + error('一次性上传数据行数应小于1000行,请分批上传') + return + } + if (!res.length) { + error('请填写至少一行数据') + return + } + let postData = []; + for (let i = 0; i < res.length; i++) { + let d = res[i]; + let obj = {}; + Object.keys(invoicingDetailsColumnKeys).map(key => { + obj[key] = d[invoicingDetailsColumnKeys[key]] || ''; + }) + postData.push(obj); + } + setPostData(postData) + let msg = '文件解析完成,点击确定按钮上传保存!' + setMsg(msg) + onSuccess({ message: msg }) + }) + }}> + + + {msg} +
最大不超过200M,导入文件需与 + download()} style={{ cursor: 'pointer', color: '#0066FF' }}>导入模板 + 一致
+ +
+ ) +} + +function mapStateToProps(state) { + const { auth, global } = state; + return { + user: auth.user, + actions: global.actions, + } +} + +export default connect(mapStateToProps)(ImportInvoicingDetailsModal); \ No newline at end of file diff --git a/web/client/src/sections/business/containers/performanceReport/invoicingDetails.jsx b/web/client/src/sections/business/containers/performanceReport/invoicingDetails.jsx index 34660cf..e677485 100644 --- a/web/client/src/sections/business/containers/performanceReport/invoicingDetails.jsx +++ b/web/client/src/sections/business/containers/performanceReport/invoicingDetails.jsx @@ -1,18 +1,86 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, useRef, useMemo } from 'react'; import { connect } from 'react-redux'; -import { Table } from '@douyinfe/semi-ui'; +import { Select, Input, Button, Table, Pagination, Skeleton } from '@douyinfe/semi-ui'; +import { SkeletonScreen, Setup } from "$components"; +import { IconSearch } from '@douyinfe/semi-icons'; +import ImportInvoicingDetailsModal from './importInvoicingDetailsModal'; +import { invoicingDetailsColumnKeys } from '../../constants/index'; import '../../style.less'; +import moment from 'moment' const InvoicingDetails = (props) => { + const { dispatch, actions } = props + const { } = actions; + const [keywordTarget, setKeywordTarget] = useState('contractNo'); + const [keyword, setKeyword] = useState('');//搜索内容 + const [limits, setLimits] = useState()//每页实际条数 + const [query, setQuery] = useState({ limit: 10, page: 0 }); //页码信息 + const [tableData, setTableData] = useState([]); + const [importModalV, setImportModalV] = useState(false); - const columns = [ - { - title: '序号', - dataIndex: 'index', - render: (text, record, index) => index + 1 - }, - ]; - const data = []; + const [setup, setSetup] = useState(false);//表格设置是否显现 + const [setupp, setSetupp] = useState([]);//实际显示的表格列表 + const INVOICINGDETAILS = "invoicingDetails"; + const renderColumns = (columnKeys) => { + let columns = []; + Object.keys(columnKeys).map(key => { + tableList[0].list.push({ name: columnKeys[key], value: key }); + switch (key) { + default: + columns.push({ + title: columnKeys[key], dataIndex: key, key: key, + render: (text, record) => text === 0 ? text : text ? text : '—', width: 32 + columnKeys[key].length * 16 + }); + break; + } + }) + return columns; + } + const tableList = [{ + title: '基础信息', + list: [] + }]; + const columns = renderColumns(invoicingDetailsColumnKeys); + function seachValueChange(value) { + setKeyword(value) + } + useEffect(() => { + localStorage.getItem(INVOICINGDETAILS) == null + ? localStorage.setItem( + INVOICINGDETAILS, + JSON.stringify(['a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a10', 'a11', 'a13']) + ) + : ""; + attribute(); + }, []); + //获取表格属性设置 + function attribute() { + const arr = localStorage.getItem(INVOICINGDETAILS) + ? JSON.parse(localStorage.getItem(INVOICINGDETAILS)) + : []; + let newColumns = []; + for (let i = 0; i < columns.length; i++) { + if (arr.indexOf(columns[i].key) > -1) { + newColumns.push(columns[i]); + } + } + setSetupp(newColumns); + } + useEffect(() => { + + }, [query]) + function handleRow(record, index) {// 给偶数行设置斑马纹 + if (index % 2 === 0) { + return { + style: { + background: '#FAFCFF', + } + }; + } else { + return {}; + } + } + const scroll = useMemo(() => ({}), []); return ( <>
@@ -23,11 +91,114 @@ const InvoicingDetails = (props) => {
/
开票明细表
-
-
- +
+
+
+
+
开票明细表
+
INVOICING DETAILS
+
+
+
+
+
+
+ +
+
+ } + showClear + placeholder='请输入关键词搜索' + value={keyword} + style={{ width: 346 }} + onChange={seachValueChange}> + +
+ +
+
+ setSetup(true)} + /> +
{ setImportModalV(true); }}> + 导入 +
+
+ 导出全部 +
+
+
+
+ +
s)} + dataSource={tableData} + bordered={false} + empty="暂无数据" + pagination={false} + + onRow={handleRow} + scroll={scroll} + /> + +
+
+
+
+ + 共{limits}条信息 + + { + setQuery({ limit: pageSize, page: currentPage - 1 }); + page.current = currentPage - 1 + }} + /> +
+
+ + + + { + importModalV ? { + setImportModalV(false); + }} /> : '' + } + {setup ? ( + { + setSetup(false); + attribute(); + }} + /> + ) : ( + "" + )} ) }