💥 feat(模块): 添加了个很棒的功能
This commit is contained in:
parent
271a4ad751
commit
facf50c0ae
@ -1,10 +1,11 @@
|
||||
const proxy = {
|
||||
'/auth': {
|
||||
target: 'http://home.robot-z.cn:7001',
|
||||
// target: 'http://home.robot-z.cn:7001',
|
||||
target: 'https://es.robot-z.cn',
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
pathRewrite: { '^/auth': '' },
|
||||
onProxyRes: function(proxyRes) {
|
||||
onProxyRes: function (proxyRes) {
|
||||
proxyRes.headers['Access-Control-Allow-Origin'] = '*';
|
||||
proxyRes.headers['Access-Control-Allow-Methods'] = 'GET,PUT,POST,DELETE,OPTIONS';
|
||||
proxyRes.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization';
|
||||
|
||||
@ -28,17 +28,22 @@ export default [
|
||||
{
|
||||
path: '/examine/index',
|
||||
name: '考评分类管理',
|
||||
component: "@/pages/examine/index",
|
||||
component: "@/pages/examine/index/index",
|
||||
},
|
||||
{
|
||||
path: '/examine/question',
|
||||
name: '考核问题管理',
|
||||
component: "@/pages/examine/question",
|
||||
component: "@/pages/examine/question/index",
|
||||
},
|
||||
{
|
||||
path: '/examine/modal',
|
||||
name: '考核模版管理',
|
||||
component: "@/pages/examine/modal",
|
||||
component: "@/pages/examine/modal/index",
|
||||
},
|
||||
{
|
||||
path: '/examine/record',
|
||||
name: '考核记录管理',
|
||||
component: "@/pages/examine/record/index",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
"crypto-js": "^4.2.0",
|
||||
"dva": "^3.0.0-alpha.1",
|
||||
"moment": "^2.30.1",
|
||||
"qrcode": "^1.5.4",
|
||||
"umi": "^4.3.24",
|
||||
"xlsx": "^0.18.5",
|
||||
"xlsx-style-fixed": "^0.0.4"
|
||||
|
||||
@ -8,6 +8,7 @@ import ProForm, { ProFormText } from "@ant-design/pro-form";
|
||||
import { Button, Col, FormInstance, Row, Tree } from "antd";
|
||||
// import { getServerpartTree } from "@/services/options";
|
||||
import useRequest from "@ahooksjs/use-request";
|
||||
import { getMerchantShopTree, getServerpartTree } from "./service";
|
||||
// import './style.less'
|
||||
// import { getMerchantShopTree } from "@/pages/Setting/Users/service";
|
||||
|
||||
@ -26,6 +27,9 @@ type DetailProps = {
|
||||
noWj?: any // 把万佳商贸隐藏
|
||||
}
|
||||
const LeftSelectTree = ({ setSelectedId, reload, actionRef, currentUser, width, otherFun, setCollapsible, collapsible, haveTest, handleGetLeftTreeData, noWj }: DetailProps) => {
|
||||
|
||||
console.log('currentUser', currentUser);
|
||||
|
||||
const searchTreeRef = useRef<FormInstance>();
|
||||
// 默认的服务区树
|
||||
const [allTreeViews, setAllTreeViews] = useState<any>()
|
||||
@ -37,7 +41,7 @@ const LeftSelectTree = ({ setSelectedId, reload, actionRef, currentUser, width,
|
||||
if (currentUser?.UserPattern === 2000) {
|
||||
data = await getMerchantShopTree({ BusinessManId: currentUser?.BusinessManID, ShowShop: false });
|
||||
} else {
|
||||
data = await getServerpartTree(currentUser?.ProvinceCode, currentUser?.CityAuthority, true, true, true)
|
||||
data = await getServerpartTree(currentUser?.provinceCode, currentUser?.CityAuthority, true, true, true, false, 1000)
|
||||
}
|
||||
console.log('datatree', data);
|
||||
|
||||
@ -233,5 +237,5 @@ const LeftSelectTree = ({ setSelectedId, reload, actionRef, currentUser, width,
|
||||
}
|
||||
|
||||
export default connect(({ user }: ConnectState) => ({
|
||||
currentUser: user.currentUser,
|
||||
}))(LeftSelectTree);
|
||||
currentUser: user.data
|
||||
}))(LeftSelectTree);
|
||||
61
src/components/leftSelectTree/service.ts
Normal file
61
src/components/leftSelectTree/service.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import request from "@/utils/requestOld"
|
||||
|
||||
export async function getServerpartTree(ProvinceCode?: number | string, ServerpartCodes?: string,
|
||||
ShowWholePower?: boolean, ShowSPRegion?: boolean, ShowRoyalty?: boolean | false, ShowCompactCount?: boolean | false, StatisticsType?: number): Promise<ServerpartTree[]> {
|
||||
// ShowRoyalty 无论传入什么都是false
|
||||
const data = await request(`/BaseInfo/GetServerpartTree?
|
||||
ProvinceCode=${ProvinceCode || ''}&ServerpartCodes=${ServerpartCodes || ''}&
|
||||
ShowWholePower=${ShowWholePower || false}&ShowWholePower=${ShowSPRegion || true}&
|
||||
ShowRoyalty=${false}&ShowCompactCount=${ShowCompactCount || false}&StatisticsType=${StatisticsType || ''}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
if (data.Result_Code !== 100) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
return data.Result_Data.List;
|
||||
}
|
||||
|
||||
|
||||
export async function getMerchantShopTree(params: { BusinessManId?: any, provinceCode?: number }) {
|
||||
const data = await request(`/FrameWork/GetMerchantShopTree`, {
|
||||
method: 'GET',
|
||||
params
|
||||
})
|
||||
|
||||
if (data.Result_Code !== 100) {
|
||||
return []
|
||||
}
|
||||
|
||||
const treeTable = wrapTreeNode(data.Result_Data.List);
|
||||
return [...treeTable];
|
||||
}
|
||||
|
||||
export function wrapTreeNode(data: any[]) {
|
||||
|
||||
const wrapData: any = data.map((item: any) => {
|
||||
const node = { ...item.node };
|
||||
|
||||
if (item.children && item.children.length > 0) {
|
||||
node.children = wrapTreeNode(item.children);
|
||||
}
|
||||
return node
|
||||
});
|
||||
return wrapData;
|
||||
}
|
||||
|
||||
|
||||
export async function handleGetServerpartDDL(params: any) {
|
||||
const data = await request(`/BaseInfo/GetServerpartDDL`, {
|
||||
method: 'GET',
|
||||
params
|
||||
})
|
||||
|
||||
if (data.Result_Code !== 100) {
|
||||
return []
|
||||
}
|
||||
|
||||
return data.Result_Data.List
|
||||
}
|
||||
|
||||
@ -193,6 +193,13 @@ const BasicLayout: FC<{ user: UserModelState, global: ProfileModelState, dispatc
|
||||
hideInMenu: false,
|
||||
name: "考核模版管理",
|
||||
path: "/examine/modal",
|
||||
},
|
||||
{
|
||||
SYSTEMMODULE_DESC: "",
|
||||
guid: "5",
|
||||
hideInMenu: false,
|
||||
name: "考核记录管理",
|
||||
path: "/examine/record",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@ -235,6 +235,11 @@ const UserModel: UserModelType = {
|
||||
path: '/examine/modal',
|
||||
name: '考核模版管理',
|
||||
component: "@/pages/examine/modal",
|
||||
},
|
||||
{
|
||||
path: '/examine/record',
|
||||
name: '考核记录管理',
|
||||
component: "@/pages/examine/record",
|
||||
}
|
||||
]
|
||||
|
||||
@ -269,6 +274,7 @@ const UserModel: UserModelType = {
|
||||
'/examine/index',
|
||||
'/examine/modal',
|
||||
'/examine/question',
|
||||
'/examine/record',
|
||||
],
|
||||
rootSubmenuKeys: handleGetRootSubmenuKeys(menuRes.data),
|
||||
indexAllMenuItemById: handleGetEachDatumFromNestedDataByKey(menuRes.data, 'id'),
|
||||
|
||||
@ -11,6 +11,9 @@ const authority: PageAuthority = {
|
||||
'/examine/question': [
|
||||
'/examine/question',
|
||||
],
|
||||
'/examine/record': [
|
||||
'/examine/record',
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -1,20 +1,17 @@
|
||||
import { connect } from "umi";
|
||||
import { useRef, useState } from "react";
|
||||
import { Button, message, Modal, Space, type FormInstance } from "antd";
|
||||
import { Children, useRef, useState } from "react";
|
||||
import { Button, message, Modal, Popconfirm, Space, type FormInstance } from "antd";
|
||||
import type { ActionType } from "@ant-design/pro-table";
|
||||
import ProTable from "@ant-design/pro-table";
|
||||
import moment from "moment";
|
||||
import LeftSelectTree from "@/components/leftSelectTree";
|
||||
import { handleGetAddExamineType, handleGetExamineTypeList } from "./service";
|
||||
import { ProForm, ProFormSwitch, ProFormText, ProFormTextArea } from "@ant-design/pro-components";
|
||||
import LeftSelectTree from "@/components/leftSelectTree/leftSelectTree";
|
||||
import { handleGetAddExamineType, handleGetDeleteExamineType, handleGetEditExamineType, handleGetExamineTypeList, handleGetExamineTypeTreeList } from "./service";
|
||||
import { ProForm, ProFormSwitch, ProFormText, ProFormTextArea, ProFormTreeSelect } from "@ant-design/pro-components";
|
||||
|
||||
|
||||
const examineIndex: React.FC<{ currentUser: any }> = (props) => {
|
||||
console.log('props', props);
|
||||
const { currentUser } = props
|
||||
|
||||
console.log('currentUser', currentUser);
|
||||
|
||||
const actionRef = useRef<ActionType>();
|
||||
const formRef = useRef<FormInstance>();
|
||||
// 弹出框的表单实例
|
||||
@ -23,12 +20,15 @@ const examineIndex: React.FC<{ currentUser: any }> = (props) => {
|
||||
const [searchParams, setSearchParams] = useState<any>()
|
||||
// 打开新增的悬浮框
|
||||
const [openAddModal, setOpenAddModal] = useState<boolean>(false)
|
||||
// 当前行数据
|
||||
const [currentRow, setCurrentRow] = useState<any>()
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>分类名称</div>,
|
||||
dataIndex: "name",
|
||||
align: 'left',
|
||||
ellipsis: true,
|
||||
width: 200,
|
||||
hideInSearch: true
|
||||
},
|
||||
@ -36,12 +36,14 @@ const examineIndex: React.FC<{ currentUser: any }> = (props) => {
|
||||
title: <div style={{ textAlign: 'center' }}>分类注释</div>,
|
||||
dataIndex: "description",
|
||||
align: 'left',
|
||||
ellipsis: true,
|
||||
width: 250,
|
||||
hideInSearch: true
|
||||
},
|
||||
{
|
||||
title: "有效状态",
|
||||
dataIndex: "status",
|
||||
ellipsis: true,
|
||||
align: 'center',
|
||||
width: 150,
|
||||
hideInSearch: true,
|
||||
@ -52,6 +54,7 @@ const examineIndex: React.FC<{ currentUser: any }> = (props) => {
|
||||
{
|
||||
title: "创建时间",
|
||||
dataIndex: "createdAt",
|
||||
ellipsis: true,
|
||||
align: 'center',
|
||||
width: 200,
|
||||
hideInSearch: true,
|
||||
@ -62,6 +65,7 @@ const examineIndex: React.FC<{ currentUser: any }> = (props) => {
|
||||
{
|
||||
title: "更新时间",
|
||||
dataIndex: "updatedAt",
|
||||
ellipsis: true,
|
||||
align: 'center',
|
||||
width: 200,
|
||||
hideInSearch: true,
|
||||
@ -77,14 +81,48 @@ const examineIndex: React.FC<{ currentUser: any }> = (props) => {
|
||||
width: 150,
|
||||
render: (_: any, record: any) => {
|
||||
return <Space>
|
||||
<a>编辑</a>
|
||||
<a>删除</a>
|
||||
<a onClick={() => {
|
||||
console.log('record', record);
|
||||
setCurrentRow(record)
|
||||
setOpenAddModal(true)
|
||||
}}>编辑</a>
|
||||
<Popconfirm
|
||||
title={"确认删除?"}
|
||||
onConfirm={() => {
|
||||
console.log('record', record);
|
||||
handleDeleteType(record.id)
|
||||
}}
|
||||
>
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
|
||||
</Space>
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 删除分类
|
||||
const handleDeleteType = async (id: number) => {
|
||||
const data = await handleGetDeleteExamineType(id)
|
||||
if (data.code === 200) {
|
||||
message.success(data.message)
|
||||
actionRef.current?.reload()
|
||||
}
|
||||
}
|
||||
|
||||
// 若children没有值 则变为null
|
||||
const handleGetNoChildren = (list: any) => {
|
||||
if (list && list.length > 0) {
|
||||
list.forEach((item) => {
|
||||
if (item.children && item.children.length > 0) {
|
||||
item.children = handleGetNoChildren(item.children)
|
||||
} else {
|
||||
item.children = null
|
||||
}
|
||||
})
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -103,12 +141,18 @@ const examineIndex: React.FC<{ currentUser: any }> = (props) => {
|
||||
expandable={{
|
||||
expandRowByClick: true
|
||||
}}
|
||||
rowKey={(record) => {
|
||||
return `${record?.id}`
|
||||
}}
|
||||
scroll={{ y: 'calc(100vh - 400px)' }}
|
||||
headerTitle={<span style={{ color: "#1890ff", fontSize: 14, fontWeight: 600 }}>考评分类管理</span>}
|
||||
search={{ span: 6 }}
|
||||
request={async (params) => {
|
||||
const data = await handleGetExamineTypeList()
|
||||
const req = {}
|
||||
let data = await handleGetExamineTypeTreeList(req)
|
||||
console.log('table', data);
|
||||
if (data && data.length > 0) {
|
||||
data = handleGetNoChildren(data)
|
||||
return { data, success: true }
|
||||
}
|
||||
return { data: [], success: true }
|
||||
@ -116,6 +160,7 @@ const examineIndex: React.FC<{ currentUser: any }> = (props) => {
|
||||
toolbar={{
|
||||
actions: [
|
||||
<Button type="primary" onClick={(e) => {
|
||||
console.log('current', currentRow);
|
||||
setOpenAddModal(true)
|
||||
}}>
|
||||
新增分类
|
||||
@ -127,40 +172,85 @@ const examineIndex: React.FC<{ currentUser: any }> = (props) => {
|
||||
</div>
|
||||
|
||||
<Modal
|
||||
title="分类"
|
||||
title={`${currentRow?.id ? '编辑' : '创建'}分类`}
|
||||
open={openAddModal}
|
||||
destroyOnClose
|
||||
onOk={() => {
|
||||
modalRef.current?.validateFields().then(async (res) => {
|
||||
console.log('res', res);
|
||||
const req = {
|
||||
name: res.name,
|
||||
description: res.description,
|
||||
sortOrder: "1",
|
||||
status: res.status,
|
||||
operator: currentUser?.operator
|
||||
let req = {}
|
||||
let data = {}
|
||||
if (currentRow?.id) {
|
||||
req = {
|
||||
...currentRow,
|
||||
parentId: res.parentId,
|
||||
name: res.name,
|
||||
description: res.description,
|
||||
status: res.status,
|
||||
operator: currentUser?.operator
|
||||
}
|
||||
data = await handleGetEditExamineType(req)
|
||||
} else {
|
||||
req = {
|
||||
parentId: res.parentId,
|
||||
name: res.name,
|
||||
description: res.description,
|
||||
sortOrder: "1",
|
||||
status: res.status,
|
||||
operator: currentUser?.operator
|
||||
}
|
||||
data = await handleGetAddExamineType(req)
|
||||
}
|
||||
const data = await handleGetAddExamineType(req)
|
||||
console.log('req', req);
|
||||
console.log('data', data);
|
||||
if (data.code === 200) {
|
||||
modalRef.current?.resetFields()
|
||||
message.success(data.message)
|
||||
setOpenAddModal(false)
|
||||
actionRef.current?.reload()
|
||||
setCurrentRow(undefined)
|
||||
} else {
|
||||
message.error(data.message)
|
||||
}
|
||||
})
|
||||
}}
|
||||
onCancel={() => {
|
||||
modalRef.current?.setFieldsValue({})
|
||||
setCurrentRow(undefined)
|
||||
setOpenAddModal(false)
|
||||
}}
|
||||
>
|
||||
<ProForm
|
||||
formRef={modalRef}
|
||||
submitter={false}
|
||||
onFinish={async (values) => {
|
||||
console.log('values', values);
|
||||
}}
|
||||
>
|
||||
<ProForm formRef={modalRef} submitter={false} request={() => {
|
||||
console.log('currentRow', currentRow);
|
||||
return { ...currentRow }
|
||||
}}>
|
||||
<ProFormTreeSelect
|
||||
label={"类别层级"}
|
||||
name={"parentId"}
|
||||
request={async () => {
|
||||
const req = {}
|
||||
const data = await handleGetExamineTypeList(req)
|
||||
console.log('dsadas', data);
|
||||
let res = [
|
||||
{
|
||||
name: '/',
|
||||
id: 0,
|
||||
children: data
|
||||
}
|
||||
]
|
||||
return res
|
||||
}}
|
||||
fieldProps={{
|
||||
treeDefaultExpandedKeys: [0],
|
||||
fieldNames: {
|
||||
label: "name",
|
||||
value: "id"
|
||||
},
|
||||
}}
|
||||
rules={[
|
||||
{ required: true, message: '请选择类别层级!' }
|
||||
]}
|
||||
/>
|
||||
|
||||
<ProFormText
|
||||
label={"类别名称"}
|
||||
name={"name"}
|
||||
@ -175,11 +265,9 @@ const examineIndex: React.FC<{ currentUser: any }> = (props) => {
|
||||
<ProFormSwitch
|
||||
label={"有效状态"}
|
||||
name={"status"}
|
||||
initialValue={true}
|
||||
initialValue={currentRow?.id ? currentRow.status : true}
|
||||
/>
|
||||
</ProForm>
|
||||
|
||||
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
37
src/pages/examine/index/service.ts
Normal file
37
src/pages/examine/index/service.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import request from "@/utils/request"
|
||||
|
||||
// 拿到类别列表接口
|
||||
export async function handleGetExamineTypeList(params?: any) {
|
||||
const data = await request.get('/question-categories', params)
|
||||
if (data.code === 200) {
|
||||
return data.data
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
// 拿树形的
|
||||
export async function handleGetExamineTypeTreeList(params?: any) {
|
||||
const data = await request.get('/question-categories/tree', params)
|
||||
if (data.code === 200) {
|
||||
return data.data
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
// 新增类别列表接口
|
||||
export async function handleGetAddExamineType(params: any) {
|
||||
const data = await request.post('/question-categories', params)
|
||||
return data
|
||||
}
|
||||
|
||||
// 删除类别接口
|
||||
export async function handleGetDeleteExamineType(params: any) {
|
||||
const data = await request.get(`/question-categories/delete/${params}`)
|
||||
return data
|
||||
}
|
||||
|
||||
// 编辑分类接口
|
||||
export async function handleGetEditExamineType(params: any) {
|
||||
const data = await request.post(`/question-categories/${params.id}`, params)
|
||||
return data
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
import { UserConnectedProps } from "@/models/user";
|
||||
import { connect } from "umi";
|
||||
|
||||
|
||||
type DetailProps = {
|
||||
|
||||
}
|
||||
const modal = ({ }: DetailProps) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
modal
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default connect(
|
||||
({ user }: { user: UserConnectedProps['user'] }) => ({
|
||||
user
|
||||
}),
|
||||
)(modal);
|
||||
553
src/pages/examine/modal/index.tsx
Normal file
553
src/pages/examine/modal/index.tsx
Normal file
@ -0,0 +1,553 @@
|
||||
import LeftSelectTree from "@/components/leftSelectTree/leftSelectTree";
|
||||
import { handleGetServerpartDDL } from "@/components/leftSelectTree/service";
|
||||
import { ActionType, FormInstance, ProCard, ProForm, ProFormList, ProFormSelect, ProFormSwitch, ProFormText, ProFormTextArea, ProTable } from "@ant-design/pro-components";
|
||||
import { Button, Col, message, Modal, Popconfirm, Row, Space } from "antd";
|
||||
import moment from "moment";
|
||||
import { useRef, useState } from "react";
|
||||
import { connect } from "umi";
|
||||
import { handleAddTemplates, handleDeleteTemplates, handleGetQuestionList, handleGetTemplatesList, handleUpdateTemplates, handleUploadFile } from "./service";
|
||||
import { handleGetExamineTypeTreeList } from "../index/service";
|
||||
import QRCode from 'qrcode';
|
||||
import { base64ToFile } from "@/utils/publicMethods";
|
||||
|
||||
const examineModal: React.FC<{ currentUser: any }> = (props) => {
|
||||
const { currentUser } = props
|
||||
|
||||
const actionRef = useRef<ActionType>();
|
||||
const formRef = useRef<FormInstance>();
|
||||
const modalActionRef = useRef<ActionType>();
|
||||
const modalFormRef = useRef<FormInstance>();
|
||||
|
||||
|
||||
|
||||
// 弹出框的表单实例
|
||||
const modalRef = useRef<FormInstance>()
|
||||
// 树相关的属性和方法
|
||||
const [selectedId, setSelectedId] = useState<string>()
|
||||
const [collapsible, setCollapsible] = useState<boolean>(false)
|
||||
|
||||
// 显示新增点位的悬浮框
|
||||
const [showPlaceModal, setShowPlaceModal] = useState<boolean>(false)
|
||||
// 当前点击选中的问题行
|
||||
const [currentRow, setCurrentRow] = useState<any>()
|
||||
// 服务区的枚举
|
||||
const [serviceObj, setServiceObj] = useState<any>()
|
||||
// 生成的二维码的初始
|
||||
const [qrCodeUrl, setQrCodeUrl] = useState<string>()
|
||||
// 选择问题的悬浮框
|
||||
const [selectQuestionModal, setSelectQuestionModal] = useState<boolean>(false)
|
||||
// 选择的问题列表 详情
|
||||
const [selectedQuestionDetail, setSelectedQuestionDetail] = useState<any>()
|
||||
// 选择的问题列表的id
|
||||
const [selectedQuestionId, setSelectedQuestionId] = useState<any>()
|
||||
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>服务区名称</div>,
|
||||
dataIndex: "serverPartName",
|
||||
hideInSearch: true,
|
||||
width: 200,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>点位名称</div>,
|
||||
dataIndex: "title",
|
||||
hideInSearch: true,
|
||||
width: 200,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>有效状态</div>,
|
||||
dataIndex: "status",
|
||||
hideInSearch: true,
|
||||
align: 'center',
|
||||
width: 100,
|
||||
ellipsis: true,
|
||||
render: (_, record) => {
|
||||
return record?.status ? '有效' : '无效'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>更新时间</div>,
|
||||
dataIndex: "updatedAt",
|
||||
hideInSearch: true,
|
||||
align: 'center',
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
render: (_, record) => {
|
||||
return record?.updatedAt ? moment(record?.updatedAt).format('YYYY-MM-DD HH:mm:ss') : ''
|
||||
}
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>备注说明</div>,
|
||||
dataIndex: "description",
|
||||
hideInSearch: true,
|
||||
width: 200,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>问题列表</div>,
|
||||
dataIndex: "questions",
|
||||
hideInSearch: true,
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
render: (_, record) => {
|
||||
return record?.questions && record?.questions.length > 0 ? JSON.stringify(record?.questions) : ''
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'option',
|
||||
align: 'center',
|
||||
hideInSearch: true,
|
||||
width: 150,
|
||||
render: (_: any, record: any) => {
|
||||
return <Space>
|
||||
<a onClick={() => {
|
||||
console.log('record', record);
|
||||
setCurrentRow(record)
|
||||
setShowPlaceModal(true)
|
||||
}}>编辑</a>
|
||||
<Popconfirm
|
||||
title={"确认删除?"}
|
||||
onConfirm={async () => {
|
||||
deleteQuestion(record?.id)
|
||||
}}
|
||||
>
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
|
||||
</Space>
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 弹出框里面的
|
||||
const modalColumns: any = [
|
||||
{
|
||||
title: "问题分类",
|
||||
dataIndex: "id",
|
||||
hideInTable: true,
|
||||
valueType: 'treeSelect',
|
||||
request: async () => {
|
||||
const data = await handleGetExamineTypeTreeList()
|
||||
console.log('data', data);
|
||||
return data && data.length > 0 ? data.map(item => ({
|
||||
title: item.name,
|
||||
value: item.id,
|
||||
children: item.children?.map((child: any) => ({
|
||||
title: child.name,
|
||||
value: child.id,
|
||||
children: child.children || []
|
||||
})) || []
|
||||
})) : []
|
||||
},
|
||||
fieldProps: {
|
||||
multiple: false,
|
||||
treeDefaultExpandAll: true,
|
||||
showSearch: true,
|
||||
treeNodeFilterProp: 'title',
|
||||
placeholder: '请选择问题分类'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "考核内容",
|
||||
dataIndex: "title",
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
hideInSearch: true
|
||||
},
|
||||
{
|
||||
title: "考核选项",
|
||||
dataIndex: "options",
|
||||
width: 500,
|
||||
ellipsis: true,
|
||||
hideInSearch: true,
|
||||
render: (_, record) => {
|
||||
return record?.options && record?.options.length > 0 ? JSON.stringify(record?.options) : ""
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 删除模版
|
||||
const deleteQuestion = async (id: number) => {
|
||||
const data = await handleDeleteTemplates({ id: id })
|
||||
if (data.code === 200) {
|
||||
message.success(data.message)
|
||||
actionRef.current?.reload()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ backgroundColor: '#fff', display: 'flex' }}>
|
||||
{/* <LeftSelectTree setSelectedId={setSelectedId} setCollapsible={setCollapsible} collapsible={collapsible} currentUser={currentUser} /> */}
|
||||
|
||||
<div style={{
|
||||
// width: !collapsible ? 'calc(100% - 300px)' : 'calc(100% - 60px)',
|
||||
width: "100%",
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
paddingRight: 0
|
||||
}}>
|
||||
<ProTable
|
||||
actionRef={actionRef}
|
||||
formRef={formRef}
|
||||
columns={columns}
|
||||
bordered
|
||||
expandable={{
|
||||
expandRowByClick: true
|
||||
}}
|
||||
headerTitle={<span style={{ color: "#1890ff", fontSize: 14, fontWeight: 600 }}>走动式点位管理</span>}
|
||||
search={{ span: 6 }}
|
||||
request={async () => {
|
||||
const req: any = {
|
||||
|
||||
}
|
||||
const data = await handleGetTemplatesList()
|
||||
if (data && data.length > 0) {
|
||||
return { data, success: true }
|
||||
}
|
||||
return { data: [], success: true }
|
||||
}}
|
||||
toolbar={{
|
||||
actions: [
|
||||
<Button type="primary" onClick={(e) => {
|
||||
setShowPlaceModal(true)
|
||||
}}>
|
||||
添加点位
|
||||
</Button>
|
||||
]
|
||||
}}
|
||||
>
|
||||
</ProTable>
|
||||
|
||||
<Modal
|
||||
width={1200}
|
||||
title={`${currentRow?.id ? '编辑' : '创建'}点位`}
|
||||
open={showPlaceModal}
|
||||
destroyOnClose
|
||||
onOk={() => {
|
||||
modalRef.current?.validateFields().then(async (res) => {
|
||||
|
||||
console.log('res', res);
|
||||
console.log('currentRow', currentRow);
|
||||
|
||||
let req = {}
|
||||
let data = {}
|
||||
if (currentRow?.id) {
|
||||
let questions: any = []
|
||||
if (selectedQuestionDetail && selectedQuestionDetail.length > 0) {
|
||||
selectedQuestionDetail.forEach((item) => {
|
||||
questions.push({
|
||||
questionId: item.id,
|
||||
isRequired: item.required,
|
||||
sortOrder: item.sortOrder
|
||||
})
|
||||
})
|
||||
} else {
|
||||
// 判断是否有改动 一样 说明没改动 那么把老的拿进去就行
|
||||
if (currentRow?.questionnaireTemplateQuestions.length === res.questions.length) {
|
||||
if (currentRow?.questionnaireTemplateQuestions && currentRow?.questionnaireTemplateQuestions.length > 0) {
|
||||
currentRow?.questionnaireTemplateQuestions.forEach((item) => {
|
||||
questions.push({
|
||||
questionId: item.question.id,
|
||||
isRequired: item.question.required,
|
||||
sortOrder: item.question.sortOrder
|
||||
})
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 不一样 说明有删除 不然走的是第一个
|
||||
if (res.questions && res.questions.length > 0) {
|
||||
res.questions.forEach((item) => {
|
||||
questions.push({
|
||||
questionId: item.id,
|
||||
isRequired: item.required,
|
||||
sortOrder: item.sortOrder
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
req = {
|
||||
...currentRow,
|
||||
title: res.title,
|
||||
serverPartName: serviceObj ? serviceObj[res.serverPartId] : "",
|
||||
serverPartId: res.serverPartId,
|
||||
questions: questions && questions.length > 0 ? questions : "",
|
||||
operator: currentUser?.operator,
|
||||
status: res.status,
|
||||
description: res.description
|
||||
}
|
||||
data = await handleUpdateTemplates(req)
|
||||
} else {
|
||||
let questions: any = []
|
||||
if (selectedQuestionDetail && selectedQuestionDetail.length > 0) {
|
||||
selectedQuestionDetail.forEach((item) => {
|
||||
questions.push({
|
||||
questionId: item.id,
|
||||
isRequired: item.required,
|
||||
sortOrder: item.sortOrder
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
req = {
|
||||
title: res.title,
|
||||
placeName: "",
|
||||
placeId: 0,
|
||||
serverPartName: serviceObj ? serviceObj[res.serverPartId] : "",
|
||||
serverPartId: res.serverPartId,
|
||||
// qrUrl: "",
|
||||
questions: questions && questions.length > 0 ? questions : "",
|
||||
operator: currentUser?.operator,
|
||||
status: res.status,
|
||||
description: res.description
|
||||
}
|
||||
data = await handleAddTemplates(req)
|
||||
console.log('datadsadsa1', data.data);
|
||||
const myQRCodeDataUrl = await QRCode.toDataURL(`pages/walkAroundManager/index?id=${data.data.id}`);
|
||||
const file = base64ToFile(myQRCodeDataUrl, `wenjuan${data.data.id}.png`);
|
||||
console.log('file', file);
|
||||
const formData = new FormData();
|
||||
formData.append("file", file, `wenjuan${data.data.id}.png`); // 确保文件名也传递
|
||||
|
||||
const fileData = await handleUploadFile(formData)
|
||||
console.log('fileData', fileData);
|
||||
let imgUrl: string = `https://es.robot-z.cn/${fileData.data.path}`
|
||||
await handleUpdateTemplates({
|
||||
...data.data,
|
||||
qrUrl: imgUrl
|
||||
})
|
||||
setQrCodeUrl(imgUrl)
|
||||
// setQrCodeUrl(myQRCodeDataUrl)
|
||||
}
|
||||
console.log('datadsadsa', data);
|
||||
if (data.code === 200) {
|
||||
// modalRef.current?.resetFields()
|
||||
message.success(data.message)
|
||||
// setShowPlaceModal(false)
|
||||
actionRef.current?.reload()
|
||||
// setCurrentRow(undefined)
|
||||
} else {
|
||||
message.error(data.message)
|
||||
}
|
||||
|
||||
})
|
||||
}}
|
||||
onCancel={() => {
|
||||
modalRef.current?.resetFields()
|
||||
setShowPlaceModal(false)
|
||||
setCurrentRow(undefined)
|
||||
setQrCodeUrl(undefined)
|
||||
}}
|
||||
>
|
||||
<ProForm formRef={modalRef} submitter={false} request={() => {
|
||||
console.log('currentRow', currentRow);
|
||||
|
||||
let questionsList: any = []
|
||||
let keyList: any = []
|
||||
if (currentRow?.questionnaireTemplateQuestions && currentRow?.questionnaireTemplateQuestions.length > 0) {
|
||||
console.log('1');
|
||||
|
||||
currentRow?.questionnaireTemplateQuestions.forEach((item) => {
|
||||
console.log('2');
|
||||
if (item.question) {
|
||||
let obj = JSON.parse(JSON.stringify(item.question))
|
||||
obj.text = obj.title
|
||||
obj.mark = JSON.stringify(obj.options)
|
||||
keyList.push(obj.id)
|
||||
questionsList.push(obj)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// setSelectedQuestionDetail
|
||||
setSelectedQuestionId(keyList)
|
||||
return {
|
||||
...currentRow,
|
||||
serverPartId: currentRow.serverPartId.toString(),
|
||||
questions: questionsList
|
||||
}
|
||||
}}>
|
||||
<Row gutter={8}>
|
||||
<Col span={8}>
|
||||
<ProFormSelect
|
||||
label={"服务区名"}
|
||||
name={"serverPartId"}
|
||||
request={async () => {
|
||||
const req = {
|
||||
ProvinceCode: currentUser?.provinceCode,
|
||||
StatisticsType: 1000
|
||||
}
|
||||
const data = await handleGetServerpartDDL(req)
|
||||
let obj: any = {}
|
||||
if (data && data.length > 0) {
|
||||
data.forEach((item) => {
|
||||
obj[item.value] = item.label
|
||||
})
|
||||
}
|
||||
setServiceObj(obj)
|
||||
return data
|
||||
}}
|
||||
fieldProps={{
|
||||
showSearch: true,
|
||||
}}
|
||||
rules={[{
|
||||
required: true,
|
||||
message: "请选择服务区!"
|
||||
}]}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col span={8}>
|
||||
<ProFormText
|
||||
label={"点位名称"}
|
||||
name={"title"}
|
||||
rules={[{
|
||||
required: true,
|
||||
message: "请输入点位名称!"
|
||||
}]}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<ProFormSwitch
|
||||
label={"有效状态"}
|
||||
name={"status"}
|
||||
initialValue={currentRow?.id ? currentRow.status : true}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={20}>
|
||||
<ProFormList
|
||||
name="questions"
|
||||
label="考核列表"
|
||||
initialValue={[]}
|
||||
creatorButtonProps={{
|
||||
position: 'bottom',
|
||||
creatorButtonText: '添加选项',
|
||||
style: { display: 'none' },
|
||||
onClick: (e) => {
|
||||
console.log('e', e);
|
||||
}
|
||||
}}
|
||||
copyIconProps={false}
|
||||
style={{ width: '100%' }}
|
||||
itemContainerStyle={{ width: '100%' }}
|
||||
itemRender={({ listDom, action }, { record, index }) => (
|
||||
<div style={{ width: '100%', display: 'flex', alignItems: 'flex-start', marginBottom: '10px' }}>
|
||||
<div style={{ flex: 1, width: '100%' }}>{listDom}</div>
|
||||
<div style={{ marginLeft: '8px', marginTop: '30px' }}>{action}</div>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<Row gutter={6} style={{ width: '100%', margin: 0 }}>
|
||||
<Col span={8}>
|
||||
<ProFormTextArea
|
||||
name="text"
|
||||
label="考核内容"
|
||||
fieldProps={{
|
||||
style: { width: '100%' }
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={16}>
|
||||
<ProFormTextArea
|
||||
name="mark"
|
||||
label="考核标准"
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</ProFormList>
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
<Button type={"primary"} onClick={() => {
|
||||
setSelectQuestionModal(true)
|
||||
}}>添加考核</Button>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<ProFormTextArea
|
||||
label={"备注说明"}
|
||||
name={"description"}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col span={24}>
|
||||
<ProFormTextArea
|
||||
label={"二维码URL"}
|
||||
name={"qrUrl"}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
{
|
||||
qrCodeUrl || currentRow?.qrUrl ?
|
||||
<img style={{ width: "150px", height: "150px" }} src={qrCodeUrl || currentRow?.qrUrl} /> : ""
|
||||
}
|
||||
</Col>
|
||||
|
||||
|
||||
</Row>
|
||||
</ProForm>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
width={1400}
|
||||
title={`点位`}
|
||||
open={selectQuestionModal}
|
||||
destroyOnClose
|
||||
onOk={() => {
|
||||
console.log('selectedQuestionDetail', selectedQuestionDetail);
|
||||
// 显示的问题列表
|
||||
let showQuestion: any = []
|
||||
if (selectedQuestionDetail && selectedQuestionDetail.length > 0) {
|
||||
selectedQuestionDetail.forEach((item) => {
|
||||
showQuestion.push({ text: item.title, mark: item.options ? JSON.stringify(item.options) : "" })
|
||||
})
|
||||
}
|
||||
modalRef.current?.setFieldsValue({
|
||||
questions: showQuestion
|
||||
})
|
||||
setSelectQuestionModal(false)
|
||||
}}
|
||||
onCancel={() => {
|
||||
setSelectQuestionModal(false)
|
||||
}}
|
||||
>
|
||||
<ProTable
|
||||
actionRef={modalActionRef}
|
||||
formRef={modalFormRef}
|
||||
columns={modalColumns}
|
||||
rowKey={"id"}
|
||||
scroll={{ y: 'calc(100vh - 500px)' }}
|
||||
request={async (params) => {
|
||||
console.log('查询参数:', params);
|
||||
const req: any = {
|
||||
categoryId: params.id
|
||||
}
|
||||
const data = await handleGetQuestionList(req)
|
||||
if (data && data.length > 0) {
|
||||
return { data, success: true }
|
||||
}
|
||||
return { data: [], success: true }
|
||||
|
||||
}}
|
||||
rowSelection={{
|
||||
type: "checkbox",
|
||||
defaultSelectedRowKeys: selectedQuestionId,
|
||||
onChange: (selectedRowKeys, selectedRows) => {
|
||||
setSelectedQuestionDetail(selectedRows)
|
||||
setSelectedQuestionId(selectedRowKeys)
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Modal>
|
||||
</div>
|
||||
</div >
|
||||
)
|
||||
}
|
||||
|
||||
export default connect(({ user }: ConnectState) => ({
|
||||
currentUser: user.data
|
||||
}))(examineModal);
|
||||
|
||||
45
src/pages/examine/modal/service.ts
Normal file
45
src/pages/examine/modal/service.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import requestOld from "@/utils/requestOld"
|
||||
import request from "@/utils/request"
|
||||
|
||||
|
||||
// 拿到模版id列表 去绑定服务区的多个站点信息 的列表接口
|
||||
export async function handleGetTemplatesList(params?: any) {
|
||||
const data = await request.get('/questionnaire-templates', params)
|
||||
if (data.code === 200) {
|
||||
return data.data
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
// 新建模版
|
||||
export async function handleAddTemplates(params?: any) {
|
||||
const data = await request.post('/questionnaire-templates', params)
|
||||
return data
|
||||
}
|
||||
|
||||
// 更新模版
|
||||
export async function handleUpdateTemplates(params?: any) {
|
||||
const data = await request.post(`/questionnaire-templates/${params.id}`, params)
|
||||
return data
|
||||
}
|
||||
|
||||
// 删除模版
|
||||
export async function handleDeleteTemplates(params?: any) {
|
||||
const data = await request.get(`/questionnaire-templates/delete/${params.id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
|
||||
export async function handleGetQuestionList(params?: any) {
|
||||
const data = await request.get(`/questions?categoryId=${params.categoryId}`,)
|
||||
if (data.code === 200) {
|
||||
return data.data
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
// 上传图片的oss接口
|
||||
export async function handleUploadFile(params?: any) {
|
||||
const data = await request.post(`/oss/upload`, params)
|
||||
return data
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
import { UserConnectedProps } from "@/models/user";
|
||||
import { connect } from "umi";
|
||||
|
||||
|
||||
type DetailProps = {
|
||||
|
||||
}
|
||||
const question = ({ }: DetailProps) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
question
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default connect(
|
||||
({ user }: { user: UserConnectedProps['user'] }) => ({
|
||||
user
|
||||
}),
|
||||
)(question);
|
||||
358
src/pages/examine/question/index.tsx
Normal file
358
src/pages/examine/question/index.tsx
Normal file
@ -0,0 +1,358 @@
|
||||
|
||||
import { ActionType, FormInstance, ProForm, ProFormDigit, ProFormList, ProFormRadio, ProFormSelect, ProFormSwitch, ProFormText, ProFormTextArea, ProFormTreeSelect, ProTable } from "@ant-design/pro-components";
|
||||
import { Button, Col, message, Modal, Popconfirm, Row, Space } from "antd";
|
||||
import { useRef, useState } from "react";
|
||||
import { connect } from "umi";
|
||||
import { handleAddQuestion, handleDeleteQuestion, handleEditQuestion, handleGetQuestionList } from "./service";
|
||||
import { handleGetExamineTypeList, handleGetExamineTypeTreeList } from "../index/service";
|
||||
import moment from "moment";
|
||||
|
||||
const examineQuestion: React.FC<{ currentUser: any }> = (props) => {
|
||||
const { currentUser } = props
|
||||
|
||||
const actionRef = useRef<ActionType>();
|
||||
const formRef = useRef<FormInstance>();
|
||||
// 显示新增问题的悬浮框
|
||||
const [showQuestionModal, setShowQuestionModal] = useState<boolean>(false)
|
||||
// 当前点击选中的问题行
|
||||
const [currentRow, setCurrentRow] = useState<any>()
|
||||
// 弹出框的表单实例
|
||||
const modalRef = useRef<FormInstance>()
|
||||
// 问题分类的枚举
|
||||
const [categoryIdObj, setCategoryIdObj] = useState<any>()
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>问题分类</div>,
|
||||
dataIndex: "description",
|
||||
width: 200,
|
||||
hideInSearch: true,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>问题内容</div>,
|
||||
dataIndex: "title",
|
||||
width: 200,
|
||||
hideInSearch: true,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>问题类型</div>,
|
||||
dataIndex: "type",
|
||||
width: 200,
|
||||
hideInSearch: true,
|
||||
ellipsis: true,
|
||||
render: (_, record) => {
|
||||
let questionType: string = record?.type && record?.type.split('_') && record?.type.split('_').length > 0 ? record?.type.split('_')[0] : ''
|
||||
return questionType === 'radio' ? '单选' : "多选"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>必填</div>,
|
||||
dataIndex: "required",
|
||||
width: 100,
|
||||
hideInSearch: true,
|
||||
ellipsis: true,
|
||||
render: (_, record) => {
|
||||
return record?.required ? '是' : "否"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>选项内容</div>,
|
||||
dataIndex: "options",
|
||||
width: 150,
|
||||
hideInSearch: true,
|
||||
ellipsis: true,
|
||||
render: (_, record) => {
|
||||
return record?.options && record?.options.length > 0 ? JSON.stringify(record?.options) : ''
|
||||
}
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>更新时间</div>,
|
||||
dataIndex: "updatedAt",
|
||||
width: 150,
|
||||
hideInSearch: true,
|
||||
ellipsis: true,
|
||||
render: (_, record) => {
|
||||
return record?.updatedAt ? moment(record?.updatedAt).format('YYYY-MM-DD HH:mm:ss') : ''
|
||||
}
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>操作人</div>,
|
||||
dataIndex: "operator",
|
||||
width: 150,
|
||||
hideInSearch: true,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'option',
|
||||
align: 'center',
|
||||
hideInSearch: true,
|
||||
width: 150,
|
||||
render: (_: any, record: any) => {
|
||||
return <Space>
|
||||
<a onClick={() => {
|
||||
console.log('record', record);
|
||||
setCurrentRow(record)
|
||||
setShowQuestionModal(true)
|
||||
}}>编辑</a>
|
||||
<Popconfirm
|
||||
title={"确认删除?"}
|
||||
onConfirm={async () => {
|
||||
deleteQuestion(record?.id)
|
||||
}}
|
||||
>
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
|
||||
</Space>
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 删除分类
|
||||
const deleteQuestion = async (id: number) => {
|
||||
const data = await handleDeleteQuestion({ id: id })
|
||||
if (data.code === 200) {
|
||||
message.success(data.message)
|
||||
actionRef.current?.reload()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{
|
||||
width: '100%',
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
paddingRight: 0
|
||||
}}>
|
||||
<ProTable
|
||||
actionRef={actionRef}
|
||||
formRef={formRef}
|
||||
columns={columns}
|
||||
bordered
|
||||
expandable={{
|
||||
expandRowByClick: true
|
||||
}}
|
||||
headerTitle={<span style={{ color: "#1890ff", fontSize: 14, fontWeight: 600 }}>考核问题管理</span>}
|
||||
search={{ span: 6 }}
|
||||
request={async (params) => {
|
||||
const data = await handleGetQuestionList()
|
||||
console.log('data', data);
|
||||
|
||||
if (data && data.length > 0) {
|
||||
return { data, success: true }
|
||||
}
|
||||
return { data: [], success: true }
|
||||
}}
|
||||
toolbar={{
|
||||
actions: [
|
||||
<Button type="primary" onClick={(e) => {
|
||||
setShowQuestionModal(true)
|
||||
}}>
|
||||
新增问题
|
||||
</Button>
|
||||
]
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<Modal
|
||||
width={800}
|
||||
title={`${currentRow?.id ? '编辑' : '创建'}问题`}
|
||||
open={showQuestionModal}
|
||||
destroyOnClose
|
||||
onOk={() => {
|
||||
modalRef.current?.validateFields().then(async (res) => {
|
||||
let req = {}
|
||||
let data = {}
|
||||
if (currentRow?.id) {
|
||||
req = {
|
||||
...currentRow,
|
||||
categoryId: res.categoryId,// 题目id
|
||||
type: `${res.selectType === 1 ? 'radio' : 'checked'}_choice`,// 题目类型
|
||||
title: res.title,// 问题内容
|
||||
required: res.required,// 是否必填
|
||||
options: res.options,
|
||||
status: res.status,
|
||||
operator: currentUser?.operator,
|
||||
description: `${res.categoryId ? categoryIdObj[res.categoryId] : ''}`
|
||||
}
|
||||
data = await handleEditQuestion(req)
|
||||
} else {
|
||||
req = {
|
||||
categoryId: res.categoryId,// 题目id
|
||||
type: `${res.selectType === 1 ? 'radio' : 'checked'}_choice`,// 题目类型
|
||||
title: res.title,// 问题内容
|
||||
required: res.required,// 是否必填
|
||||
options: res.options,
|
||||
sortOrder: 1,
|
||||
status: res.status,
|
||||
operator: currentUser?.operator,
|
||||
defaultScore: 0,
|
||||
images: [],
|
||||
description: `${res.categoryId ? categoryIdObj[res.categoryId] : ''}`
|
||||
}
|
||||
data = await handleAddQuestion(req)
|
||||
}
|
||||
console.log('datadsadsa', data);
|
||||
if (data.code === 200) {
|
||||
modalRef.current?.resetFields()
|
||||
message.success(data.message)
|
||||
setShowQuestionModal(false)
|
||||
actionRef.current?.reload()
|
||||
setCurrentRow(undefined)
|
||||
} else {
|
||||
message.error(data.message)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
}}
|
||||
onCancel={() => {
|
||||
modalRef.current?.resetFields()
|
||||
setShowQuestionModal(false)
|
||||
setCurrentRow(undefined)
|
||||
}}
|
||||
>
|
||||
<ProForm formRef={modalRef} submitter={false} request={() => {
|
||||
console.log('currentRow', currentRow);
|
||||
return {
|
||||
...currentRow,
|
||||
selectType: currentRow.type.split('_')[0] === 'checked' ? 2 : 1
|
||||
}
|
||||
}}>
|
||||
<Row gutter={8}>
|
||||
<Col span={12}>
|
||||
<ProFormTreeSelect
|
||||
label={"问题分类"}
|
||||
name={"categoryId"}
|
||||
rules={[
|
||||
{ required: true, message: '请选择问题分类!' }
|
||||
]}
|
||||
request={async () => {
|
||||
|
||||
|
||||
const req = {}
|
||||
const data = await handleGetExamineTypeTreeList(req)
|
||||
console.log('dsadas', data);
|
||||
let res = [
|
||||
{
|
||||
name: '/',
|
||||
id: 0,
|
||||
children: data
|
||||
}
|
||||
]
|
||||
let obj: any = {}
|
||||
const labelList = await handleGetExamineTypeList()
|
||||
if (labelList && labelList.length > 0) {
|
||||
labelList.forEach((item) => {
|
||||
obj[item.id] = item.name
|
||||
})
|
||||
}
|
||||
setCategoryIdObj(obj)
|
||||
return res
|
||||
}}
|
||||
fieldProps={{
|
||||
treeDefaultExpandedKeys: [0],
|
||||
fieldNames: {
|
||||
label: "name",
|
||||
value: "id"
|
||||
},
|
||||
showSearch: true,
|
||||
filterTreeNode: (input, treeNode) => {
|
||||
return (treeNode?.name ?? '').toLowerCase().indexOf(input.toLowerCase()) >= 0;
|
||||
},
|
||||
treeNodeFilterProp: 'name'
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<ProFormText
|
||||
label={"问题内容"}
|
||||
name={"title"}
|
||||
rules={[
|
||||
{ required: true, message: '请输入问题!' }
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col span={6}>
|
||||
<ProFormSwitch
|
||||
label={"是否必填"}
|
||||
name={"required"}
|
||||
initialValue={currentRow?.id ? currentRow.required : true}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<ProFormSwitch
|
||||
label={"有效状态"}
|
||||
name={"status"}
|
||||
initialValue={currentRow?.id ? currentRow.status : true}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<ProFormRadio.Group
|
||||
label={"题目类型"}
|
||||
name={"selectType"}
|
||||
fieldProps={{
|
||||
options: [{ label: "单选", value: 1 }, { label: "多选", value: 2 }],
|
||||
}}
|
||||
initialValue={1}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<ProFormList
|
||||
name="options"
|
||||
label="选项内容"
|
||||
initialValue={[]}
|
||||
creatorButtonProps={{
|
||||
position: 'bottom',
|
||||
creatorButtonText: '添加选项'
|
||||
}}
|
||||
copyIconProps={false}
|
||||
style={{ width: '100%' }}
|
||||
itemContainerStyle={{ width: '100%' }}
|
||||
itemRender={({ listDom, action }, { record, index }) => (
|
||||
<div style={{ width: '100%', display: 'flex', alignItems: 'flex-start', marginBottom: '10px' }}>
|
||||
<div style={{ flex: 1, width: '100%' }}>{listDom}</div>
|
||||
<div style={{ marginLeft: '8px', marginTop: '30px' }}>{action}</div>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<Row gutter={6} style={{ width: '100%', margin: 0 }}>
|
||||
<Col span={16}>
|
||||
<ProFormTextArea
|
||||
name="text"
|
||||
label="选项"
|
||||
fieldProps={{
|
||||
style: { width: '100%' }
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<ProFormDigit
|
||||
name="mark"
|
||||
label="分值"
|
||||
fieldProps={{
|
||||
style: { width: '100%' },
|
||||
defaultValue: 0
|
||||
}}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</ProFormList>
|
||||
</Col>
|
||||
</Row>
|
||||
</ProForm>
|
||||
</Modal>
|
||||
</div >
|
||||
)
|
||||
}
|
||||
|
||||
export default connect(({ user }: ConnectState) => ({
|
||||
currentUser: user.data
|
||||
}))(examineQuestion);
|
||||
30
src/pages/examine/question/service.ts
Normal file
30
src/pages/examine/question/service.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import request from "@/utils/request"
|
||||
|
||||
// 拿到问题列表接口
|
||||
export async function handleGetQuestionList(params?: any) {
|
||||
const data = await request.get('/questions', params)
|
||||
if (data.code === 200) {
|
||||
return data.data
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
// 新增问题接口
|
||||
export async function handleAddQuestion(params?: any) {
|
||||
const data = await request.post('/questions', params)
|
||||
return data
|
||||
}
|
||||
|
||||
// 编辑问题接口
|
||||
export async function handleEditQuestion(params?: any) {
|
||||
const data = await request.post(`/questions/${params.id}`, params)
|
||||
return data
|
||||
}
|
||||
|
||||
// 删除问题
|
||||
export async function handleDeleteQuestion(params?: any) {
|
||||
const data = await request.get(`/questions/delete/${params.id}`)
|
||||
return data
|
||||
}
|
||||
|
||||
|
||||
165
src/pages/examine/record/index.tsx
Normal file
165
src/pages/examine/record/index.tsx
Normal file
@ -0,0 +1,165 @@
|
||||
import { ConnectState } from "@/models/global";
|
||||
import { ActionType, FormInstance, ProTable } from "@ant-design/pro-components";
|
||||
import { useRef, useState } from "react";
|
||||
import { connect } from "umi";
|
||||
import { handleGetRecordList } from "./service";
|
||||
import moment from "moment";
|
||||
import { Button, Image } from "antd";
|
||||
|
||||
const examineRecord: React.FC<{ currentUser: any }> = (props) => {
|
||||
const { currentUser } = props
|
||||
|
||||
const actionRef = useRef<ActionType>();
|
||||
const formRef = useRef<FormInstance>();
|
||||
// 显示的附件数据
|
||||
const [showImgList, setShowImgList] = useState<string[]>([])
|
||||
// 预览图片
|
||||
const [imagePreviewVisible, setImagePreviewVisible] = useState<boolean>(false)
|
||||
// 预览的索引
|
||||
const [previewIndex, setPreviewIndex] = useState<number>(0)
|
||||
|
||||
const columns: any = [
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>服务区名称</div>,
|
||||
dataIndex: "serverPartName",
|
||||
hideInSearch: true,
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
render: (_, record) => {
|
||||
return record?.template.serverPartName ? record?.template.serverPartName : "-"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>站点名称</div>,
|
||||
dataIndex: "placeName",
|
||||
hideInSearch: true,
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
render: (_, record) => {
|
||||
return record?.template.title ? record?.template.title : "-"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>巡查内容</div>,
|
||||
dataIndex: "uploadResult",
|
||||
hideInSearch: true,
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
render: (_, record) => {
|
||||
let extendObj = record?.extend ? JSON.parse(record?.extend) : ""
|
||||
return extendObj?.uploadResult ? extendObj?.uploadResult : "-"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>巡查结果</div>,
|
||||
dataIndex: "uploadResult",
|
||||
hideInSearch: true,
|
||||
width: 350,
|
||||
ellipsis: true,
|
||||
render: (_, record) => {
|
||||
let obj: any = {}
|
||||
if (record?.questionResponses && record?.questionResponses.length > 0) {
|
||||
record?.questionResponses.forEach((item) => {
|
||||
obj[item.question.title] = JSON.stringify(item.choiceResponse)
|
||||
})
|
||||
}
|
||||
return obj ? JSON.stringify(obj) : "-"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>巡查时间</div>,
|
||||
dataIndex: "createdAt",
|
||||
hideInSearch: true,
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
align: 'center',
|
||||
render: (_, record) => {
|
||||
return record?.createdAt ? moment(record?.createdAt).format('YYYY-MM-DD HH:mm:ss') : '-'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: <div style={{ textAlign: 'center' }}>现场图片</div>,
|
||||
dataIndex: "placeName",
|
||||
hideInSearch: true,
|
||||
width: 150,
|
||||
ellipsis: true,
|
||||
align: 'center',
|
||||
render: (_, record) => {
|
||||
let extendObj = record?.extend ? JSON.parse(record?.extend) : ""
|
||||
let imgList = extendObj.imgsList
|
||||
return imgList && imgList.length > 0 ?
|
||||
<Button type="primary" onClick={() => {
|
||||
setShowImgList(imgList)
|
||||
setImagePreviewVisible(true)
|
||||
}}>查看附件</Button> : "-"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div style={{ backgroundColor: '#fff', display: 'flex' }}>
|
||||
<div style={{
|
||||
// width: !collapsible ? 'calc(100% - 300px)' : 'calc(100% - 60px)',
|
||||
width: "100%",
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
paddingRight: 0
|
||||
}}>
|
||||
<ProTable
|
||||
actionRef={actionRef}
|
||||
formRef={formRef}
|
||||
columns={columns}
|
||||
bordered
|
||||
expandable={{
|
||||
expandRowByClick: true
|
||||
}}
|
||||
headerTitle={<span style={{ color: "#1890ff", fontSize: 14, fontWeight: 600 }}>考核记录管理</span>}
|
||||
search={{ span: 6 }}
|
||||
request={async () => {
|
||||
const req: any = {
|
||||
|
||||
}
|
||||
const data = await handleGetRecordList()
|
||||
console.log('data', data);
|
||||
|
||||
if (data && data.length > 0) {
|
||||
return { data, success: true }
|
||||
}
|
||||
return { data: [], success: true }
|
||||
}}
|
||||
toolbar={{
|
||||
|
||||
}}
|
||||
>
|
||||
</ProTable>
|
||||
</div>
|
||||
|
||||
{
|
||||
showImgList && showImgList.length > 0 && <div style={{ display: 'none' }}>
|
||||
|
||||
<Image.PreviewGroup
|
||||
|
||||
preview={{
|
||||
visible: imagePreviewVisible,
|
||||
onVisibleChange: vis => {
|
||||
setImagePreviewVisible(vis)
|
||||
},
|
||||
current: previewIndex
|
||||
}}>
|
||||
{
|
||||
showImgList.map((n) =>
|
||||
<Image src={n} key={n} />
|
||||
)
|
||||
}
|
||||
</Image.PreviewGroup>
|
||||
|
||||
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default connect(({ user }: ConnectState) => ({
|
||||
currentUser: user.data
|
||||
}))(examineRecord);
|
||||
13
src/pages/examine/record/service.ts
Normal file
13
src/pages/examine/record/service.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import request from "@/utils/request"
|
||||
|
||||
// 拿到问题列表接口
|
||||
export async function handleGetRecordList(params?: any) {
|
||||
const data = await request.get('/questionnaire-responses', params)
|
||||
if (data.code === 200) {
|
||||
return data.data
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,16 +0,0 @@
|
||||
import request from "@/utils/request"
|
||||
|
||||
// 拿到类别列表接口
|
||||
export async function handleGetExamineTypeList(params?: any) {
|
||||
const data = await request.get('/question-categories', params)
|
||||
if (data.code === 200) {
|
||||
return data.data
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
// 新增类别列表接口
|
||||
export async function handleGetAddExamineType(params: any) {
|
||||
const data = await request.post('/question-categories', params)
|
||||
return data
|
||||
}
|
||||
@ -8,7 +8,7 @@ import * as XLSX from 'xlsx'; // 读写数据的核心工具(无需写样式
|
||||
import XLSXStyle from 'xlsx-style-fixed';
|
||||
import moment from "moment";
|
||||
import { handleFormatNumber } from "@/utils/publicMethods";
|
||||
import LeftSelectTree from "@/components/leftSelectTree";
|
||||
import LeftSelectTree from "@/components/leftSelectTree/leftSelectTree";
|
||||
import { UserConnectedProps } from "@/models/user";
|
||||
|
||||
|
||||
|
||||
@ -22,3 +22,16 @@ export const handleFormatNumber = (num: any) => {
|
||||
return `${integer}.${decimal}`;
|
||||
};
|
||||
|
||||
|
||||
// base64转为文件格式
|
||||
export const base64ToFile = (base64Data: any, filename = "qrcode.png") => {
|
||||
const arr = base64Data.split(",");
|
||||
const mime = arr[0].match(/:(.*?);/)[1]; // 提取 MIME 类型
|
||||
const bstr = atob(arr[1]); // 解码 Base64
|
||||
let n = bstr.length;
|
||||
const u8arr = new Uint8Array(n);
|
||||
while (n--) {
|
||||
u8arr[n] = bstr.charCodeAt(n);
|
||||
}
|
||||
return new File([u8arr], filename, { type: mime });
|
||||
}
|
||||
|
||||
@ -19,10 +19,12 @@ instance.interceptors.request.use(
|
||||
// config.data = preprocessData(JSON.stringify(config.data)); // 调用预处理函数
|
||||
// }
|
||||
|
||||
const isUpload = config.url?.includes("/oss/upload");
|
||||
|
||||
config.headers = {
|
||||
...config.headers,
|
||||
Authorization: `Bearer ${localStorage.getItem('Authorization') || ''}`,
|
||||
"Content-Type": "application/json;charset=utf-8"
|
||||
"Content-Type": isUpload ? "multipart/form-data" : "application/json;charset=utf-8",
|
||||
} as AxiosRequestHeaders;
|
||||
|
||||
return config;
|
||||
|
||||
151
src/utils/requestOld.ts
Normal file
151
src/utils/requestOld.ts
Normal file
@ -0,0 +1,151 @@
|
||||
import axios from 'axios';
|
||||
import { getDvaApp } from 'umi';
|
||||
import { notification } from 'antd';
|
||||
import type { AxiosRequestHeaders } from 'axios/index';
|
||||
import CryptoJS from "crypto-js";
|
||||
|
||||
const { UMI_APP_BASEURL } = process.env;
|
||||
|
||||
// const instance = axios.create({ baseURL: UMI_APP_BASEURL });
|
||||
const instance = axios.create({ baseURL: 'https://api.eshangtech.com/EShangApiMain' });
|
||||
// const instance = axios.create({ baseURL: '/auth' });
|
||||
|
||||
|
||||
|
||||
instance.interceptors.request.use(
|
||||
(config) => {
|
||||
// 对data数据进行加密
|
||||
// if (config.data) {
|
||||
// config.data = preprocessData(JSON.stringify(config.data)); // 调用预处理函数
|
||||
// }
|
||||
|
||||
config.headers = {
|
||||
...config.headers,
|
||||
Authorization: `Bearer ${localStorage.getItem('Authorization') || ''}`,
|
||||
"Content-Type": "application/json;charset=utf-8"
|
||||
} as AxiosRequestHeaders;
|
||||
|
||||
return config;
|
||||
},
|
||||
(error) => Promise.reject(error),
|
||||
);
|
||||
|
||||
instance.interceptors.response.use(
|
||||
//状态码为2xx的时候执行
|
||||
(response) => {
|
||||
const { data } = response;
|
||||
|
||||
if (data.code !== 200 && data.Result_Code !== 100) {
|
||||
notification.error({
|
||||
message: data.message,
|
||||
});
|
||||
}
|
||||
|
||||
const timestamp = getFormattedDate()
|
||||
|
||||
return data
|
||||
},
|
||||
//状态码不是2xx的时候执行
|
||||
(error) => {
|
||||
const { response } = error;
|
||||
|
||||
if (response && response.status === 401) {
|
||||
// // 清除本地存储的token
|
||||
// localStorage.removeItem('Authorization');
|
||||
// // 重定向到登录页
|
||||
// window.location.href = '/user/login';
|
||||
// notification.error({
|
||||
// message: response?.data?.message || '请求失败',
|
||||
// description: error.message
|
||||
// });
|
||||
} else {
|
||||
notification.error({
|
||||
message: response?.data?.message || '请求失败',
|
||||
description: error.message
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.reject({
|
||||
code: response?.status || 500,
|
||||
message: response?.data?.message || '请求失败'
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
// 加密
|
||||
const encryptAESECB = (data: string, key: string) => {
|
||||
// const cipher = CryptoJS.createCipheriv('aes-128-ecb', key, null); // ECB 模式不需要 IV
|
||||
const newKey = CryptoJS.enc.Utf8.parse(key); // 密钥必须是 16 字节
|
||||
const cipher = CryptoJS.AES.encrypt(data, newKey, {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
let encrypted = cipher.ciphertext.toString(CryptoJS.enc.Hex);
|
||||
// let encrypted = cipher.update(data, 'utf8', 'hex');
|
||||
// encrypted += cipher.final('hex');
|
||||
return encrypted;
|
||||
}
|
||||
|
||||
// 解密
|
||||
const decryptAESECB = (data: string, key: string) => {
|
||||
// const decipher = CryptoJS.createDecipheriv('aes-128-ecb', key, null);
|
||||
// let decrypted = decipher.update(data, 'hex', 'utf8');
|
||||
// decrypted += decipher.final('utf8');
|
||||
const newKey = CryptoJS.enc.Utf8.parse(key);
|
||||
|
||||
const encryptedData = CryptoJS.enc.Hex.parse(data);
|
||||
|
||||
// 解密操作
|
||||
const decrypted = CryptoJS.AES.decrypt({ ciphertext: encryptedData }, newKey, {
|
||||
mode: CryptoJS.mode.ECB, // ECB 模式
|
||||
padding: CryptoJS.pad.Pkcs7 // PKCS7 填充方式
|
||||
});
|
||||
// 将解密后的结果转为 UTF-8 字符串
|
||||
const decryptedText = decrypted.toString(CryptoJS.enc.Utf8);
|
||||
return decryptedText;
|
||||
}
|
||||
|
||||
// md5 签名
|
||||
const md5 = (key: string, data: string, timestamp: string) => {
|
||||
const text = "s" + key + data + timestamp;
|
||||
return CryptoJS.MD5(text).toString(CryptoJS.enc.Hex);
|
||||
}
|
||||
|
||||
// 生成签名戳
|
||||
const getFormattedDate = () => {
|
||||
const date = new Date();
|
||||
const year = date.getFullYear(); // 获取年份 (yyyy)
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0'); // 获取月份 (MM)
|
||||
const day = String(date.getDate()).padStart(2, '0'); // 获取日期 (dd)
|
||||
const hours = String(date.getHours()).padStart(2, '0'); // 获取小时 (HH)
|
||||
return `es0${year}${month}${day}${hours}0es`; // 拼接成 yyyyMMddHH 格式
|
||||
}
|
||||
|
||||
// 加密方法
|
||||
const preprocessData = (data: string) => {
|
||||
console.log('data', data);
|
||||
// YYYYMMDD
|
||||
let timestamp = getFormattedDate()
|
||||
console.log('timestamp', timestamp);
|
||||
// 秒为单位的时间戳
|
||||
let timeSecond = parseInt((new Date().getTime() / 1000).toString())
|
||||
console.log('timeSecond', timeSecond);
|
||||
// 数据的加密
|
||||
let encryptionData = encryptAESECB(data, timestamp)
|
||||
console.log('encryptionData', encryptionData);
|
||||
// md5签名方法
|
||||
let md5Data = md5(timestamp, encryptionData, timestamp)
|
||||
console.log('md5Data', md5Data);
|
||||
|
||||
let res = {
|
||||
data: encryptionData,
|
||||
timestamp: timeSecond,
|
||||
sign: md5Data
|
||||
}
|
||||
console.log('res', res);
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
export default instance;
|
||||
Binary file not shown.
88
yarn.lock
88
yarn.lock
@ -4260,7 +4260,7 @@ camelcase-keys@^7.0.0:
|
||||
quick-lru "^5.1.1"
|
||||
type-fest "^1.2.1"
|
||||
|
||||
camelcase@^5.3.1:
|
||||
camelcase@^5.0.0, camelcase@^5.3.1:
|
||||
version "5.3.1"
|
||||
resolved "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
||||
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||
@ -4367,6 +4367,15 @@ click-to-react-component@1.1.0:
|
||||
htm "^3.1.0"
|
||||
react-merge-refs "^1.1.0"
|
||||
|
||||
cliui@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.npmmirror.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
|
||||
integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
|
||||
dependencies:
|
||||
string-width "^4.2.0"
|
||||
strip-ansi "^6.0.0"
|
||||
wrap-ansi "^6.2.0"
|
||||
|
||||
cliui@^8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
|
||||
@ -4880,7 +4889,7 @@ decamelize-keys@^1.1.0:
|
||||
decamelize "^1.1.0"
|
||||
map-obj "^1.0.0"
|
||||
|
||||
decamelize@^1.1.0:
|
||||
decamelize@^1.1.0, decamelize@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||
integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==
|
||||
@ -5013,6 +5022,11 @@ diffie-hellman@^5.0.3:
|
||||
miller-rabin "^4.0.0"
|
||||
randombytes "^2.0.0"
|
||||
|
||||
dijkstrajs@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmmirror.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz#4c8dbdea1f0f6478bff94d9c49c784d623e4fc23"
|
||||
integrity sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==
|
||||
|
||||
dir-glob@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
|
||||
@ -6249,7 +6263,7 @@ gensync@^1.0.0-beta.2:
|
||||
resolved "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||
integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
|
||||
|
||||
get-caller-file@^2.0.5:
|
||||
get-caller-file@^2.0.1, get-caller-file@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
@ -8542,6 +8556,11 @@ pluralize@^8.0.0:
|
||||
resolved "https://registry.npmmirror.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
|
||||
integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
|
||||
|
||||
pngjs@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.npmmirror.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb"
|
||||
integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==
|
||||
|
||||
point-in-polygon@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmmirror.com/point-in-polygon/-/point-in-polygon-1.1.0.tgz#b0af2616c01bdee341cbf2894df643387ca03357"
|
||||
@ -9040,6 +9059,15 @@ qiankun@^2.10.1:
|
||||
lodash "^4.17.11"
|
||||
single-spa "^5.9.2"
|
||||
|
||||
qrcode@^1.5.4:
|
||||
version "1.5.4"
|
||||
resolved "https://registry.npmmirror.com/qrcode/-/qrcode-1.5.4.tgz#5cb81d86eb57c675febb08cf007fff963405da88"
|
||||
integrity sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==
|
||||
dependencies:
|
||||
dijkstrajs "^1.0.1"
|
||||
pngjs "^5.0.0"
|
||||
yargs "^15.3.1"
|
||||
|
||||
qs@6.13.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906"
|
||||
@ -9870,6 +9898,11 @@ require-from-string@^2.0.2:
|
||||
resolved "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
|
||||
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
|
||||
|
||||
require-main-filename@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmmirror.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
|
||||
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
|
||||
|
||||
resize-observer-polyfill@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.npmmirror.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
|
||||
@ -10108,6 +10141,11 @@ serve-static@1.16.2:
|
||||
parseurl "~1.3.3"
|
||||
send "0.19.0"
|
||||
|
||||
set-blocking@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||
integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==
|
||||
|
||||
set-function-length@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
|
||||
@ -11347,6 +11385,11 @@ which-collection@^1.0.1, which-collection@^1.0.2:
|
||||
is-weakmap "^2.0.2"
|
||||
is-weakset "^2.0.3"
|
||||
|
||||
which-module@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmmirror.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409"
|
||||
integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==
|
||||
|
||||
which-typed-array@^1.1.16, which-typed-array@^1.1.18:
|
||||
version "1.1.18"
|
||||
resolved "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.18.tgz#df2389ebf3fbb246a71390e90730a9edb6ce17ad"
|
||||
@ -11397,6 +11440,15 @@ word@~0.3.0:
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrap-ansi@^6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
|
||||
integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrap-ansi@^8.1.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
|
||||
@ -11458,6 +11510,11 @@ xtend@^4.0.0:
|
||||
resolved "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||
|
||||
y18n@^4.0.0:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.npmmirror.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
|
||||
integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
|
||||
|
||||
y18n@^5.0.5:
|
||||
version "5.0.8"
|
||||
resolved "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
|
||||
@ -11478,6 +11535,14 @@ yaml@^1.10.0:
|
||||
resolved "https://registry.npmmirror.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
||||
|
||||
yargs-parser@^18.1.2:
|
||||
version "18.1.3"
|
||||
resolved "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
|
||||
integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
|
||||
dependencies:
|
||||
camelcase "^5.0.0"
|
||||
decamelize "^1.2.0"
|
||||
|
||||
yargs-parser@^20.2.9:
|
||||
version "20.2.9"
|
||||
resolved "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
|
||||
@ -11488,6 +11553,23 @@ yargs-parser@^21.1.1:
|
||||
resolved "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
|
||||
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
|
||||
|
||||
yargs@^15.3.1:
|
||||
version "15.4.1"
|
||||
resolved "https://registry.npmmirror.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
|
||||
integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
|
||||
dependencies:
|
||||
cliui "^6.0.0"
|
||||
decamelize "^1.2.0"
|
||||
find-up "^4.1.0"
|
||||
get-caller-file "^2.0.1"
|
||||
require-directory "^2.1.1"
|
||||
require-main-filename "^2.0.0"
|
||||
set-blocking "^2.0.0"
|
||||
string-width "^4.2.0"
|
||||
which-module "^2.0.0"
|
||||
y18n "^4.0.0"
|
||||
yargs-parser "^18.1.2"
|
||||
|
||||
yargs@^17.5.1:
|
||||
version "17.7.2"
|
||||
resolved "https://registry.npmmirror.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user