Commit 7c8ae382 authored by wangjing2's avatar wangjing2

add

parent a1b5ebb3
/node_modules
/.env.local
/.umirc.local.ts
/config/config.local.ts
/src/.umi
/src/.umi-production
/src/.umi-test
/dist
.swc
.history
registry=https://registry.npmmirror.com/
import { defineConfig } from "umi";
import env from "./env";
import routes from "./routes";
import proxy from "./proxy";
const { REACT_APP_ENV = "dev", NODE_ENV } = process.env;
export default defineConfig({
outputPath: 'taian',
npmClient: "yarn",
plugins: [
"@umijs/plugins/dist/antd",
"@umijs/plugins/dist/locale",
"@umijs/plugins/dist/layout",
"@umijs/plugins/dist/initial-state",
"@umijs/plugins/dist/model",
"@umijs/plugins/dist/access",
"umi-plugin-keep-alive"
],
antd: {},
model: {},
initialState: {},
define: env[REACT_APP_ENV],
routes,
hash: true,
history: {
type: 'hash',
},
manifest: {
basePath: "/",
},
proxy: proxy[REACT_APP_ENV || "dev"],
publicPath: NODE_ENV !== "development" ? "./" : "/",
});
const Settings = {
title: 'WMS仓库管理系统',
name: 'WMS仓库管理系统',
primaryColor: '#001529',
layout: 'side',
contentWidth: 'Fluid',
fixedHeader: false,
fixSiderbar: false,
pwa: false,
// "logo": "/staticfile/group1/M00/00/00/oYYBAGNuFCqARiJKAAGIO2gWB34399.png",
logo: './logo.png',
siderMenuType: 'sub'
};
export default Settings;
\ No newline at end of file
export default {
dev:{
"REACT_APP_URL":"/tawms", //"http://118.89.86.27:7001"
},
test:{
"REACT_APP_URL":"http://localhost:7001"
},
prod:{
"REACT_APP_URL":"/tawms"
}
}
/**
* 在生产环境 代理是无法生效的,所以这里没有生产环境的配置
* -------------------------------
* The agent cannot take effect in the production environment
* so there is no configuration of the production environment
* For details, please see
* https://pro.ant.design/docs/deploy
*/
export default {
dev: {
// localhost:8000/api/** -> https://preview.pro.ant.design/api/**
"/tawms/": {
// 要代理的地址
// target: "http://192.168.40.18/wms/", //39:28040 18/wms/
// target: "http://192.168.40.203:28040", //39:28040 18/wms/ dj
target: "http://192.168.40.203:38040", //39:28040 18/wms/ jf
// target: "http://192.168.40.203:28040", //39:28040 18/wms/ jf
changeOrigin: true,
pathRewrite: {
"^/tawms": "",
},
},
"/staticfile/": {
target: "http://192.168.40.2/",
changeOrigin: true,
pathRewrite: {
"^/staticfile": "",
},
},
},
test: {
"/api/": {
target: "https://proapi.azurewebsites.net",
changeOrigin: true,
pathRewrite: {
"^": "",
},
},
},
pre: {
"/api/": {
target: "your pre url",
changeOrigin: true,
pathRewrite: {
"^": "",
},
},
},
};
\ No newline at end of file
/*
* @Author: wuhao930406 1148547900@qq.com
* @Date: 2023-10-17 10:14:53
* @LastEditors: wuhao930406 1148547900@qq.com
* @LastEditTime: 2023-10-19 14:58:59
* @FilePath: /standaloneframe/frontend/config/routes.js
* @Description:
*
* Copyright (c) 2023 by ${git_name_email}, All Rights Reserved.
*/
export default [
{
path: "/user",
layout: false,
routes: [
{
path: "/user",
routes: [
{
name: "登录",
path: "/user/login",
component: "./Login",
},
],
},
],
},
{
path: "/",
name: "欢迎使用",
component: "@/layouts/layout",
routes: [
{
path: "/",
redirect: "/home",
},
{
name: "首页",
path: "/home",
component: "./index",
},
{
name: "系统管理",
path: "/system",
icon: "setting",
routes: [
{
path: "/system",
redirect: "/system/role",
},
{
name: "角色管理",
path: "/system/role",
component: "./system/Role",
},
{
name: "用户管理",
path: "/system/user",
component: "./system/User",
},
{
name: "数据字典",
path: "/system/dictionary",
component: "./system/Dictionary",
},
{
name: "组织管理",
path: "/system/department",
component: "./system/Department",
},
{
name: "组织管理",
path: "/system/factory",
component: "./system/Factory",
},
{
component: "./404",
},
],
},
{
name: "基础数据",
path: "/basicdata",
icon: "database",
routes: [
{
path: "/basicdata",
redirect: "/basicdata/warehouse",
},
{
name: "仓库管理",
path: "/basicdata/warehouse",
component: "./basicdata/Warehouse",
},
{
name: "库位管理",
path: "/basicdata/kuwei",
component: "./basicdata/Kuwei",
},
{
name: "工位管理",
path: "/basicdata/station",
component: "./basicdata/Station",
},
{
name: "物料管理",
path: "/basicdata/material",
component: "./basicdata/Material",
},
{
component: "./404"
},
],
},
{
name: "入库管理",
path: "/instore",
icon: "import",
routes: [
{
path: "/instore",
redirect: "/instore/manage",
},
{
name: "装配入库",
path: "/instore/instoreapplication",
component: "./instore/Instoreapplication",
},
{
name: "生产退料",
path: "/instore/backapplication",
component: "./instore/Backapplication",
},
{
name: "入库单管理",
path: "/instore/manage",
component: "./instore/Manage",
},
{
component: "./404"
},
],
},
{
name: "出库管理",
path: "/outstore",
icon: "export",
routes: [
{
path: "/outstore",
redirect: "/outstore/material",
},
{
name: "叫料申请单",
path: "/outstore/material",
component: "./outstore/Material",
},
{
name: "检验出库申请",
path: "/outstore/inspect",
component: "./outstore/Inspect",
},
{
name: "出库单管理",
path: "/outstore/outbound",
component: "./outstore/Outbound",
},
{
name: "调拨单管理",
path: "/outstore/allot",
component: "./outstore/Allot",
},
{
name: "移库单管理",
path: "/outstore/relocation",
component: "./outstore/Relocation",
},
{
component: "./404",
},
],
},
{
name: "库存管理",
path: "/inventory",
icon: "credit-card",
routes: [
{
path: "/inventory",
redirect: "/inventory/inventoryquery",
},
{
name: "库存查询",
path: "/inventory/inventoryquery",
component: "./inventory/Inventoryquery",
},
{
name: "出入库明细",
path: "/inventory/Inoutstoragedetail",
component: "./inventory/Inoutstoragedetail",
},
{
component: "./404",
},
],
},
{
name: "托盘管理",
path: "/tray",
icon: "inbox",
routes: [
{
path: "/tray",
redirect: "/tray/traymanage",
},
{
name: "托盘管理",
path: "/tray/traymanage",
component: "./tray/Traymanage",
},
{
name: "空托盘调拨",
path: "/tray/allot",
component: "./tray/Allot",
},
{
component: "./404"
},
],
},
{
name: "任务管理",
path: "/task",
icon: "ordered-list",
routes: [
{
path: "/task",
redirect: "/task/taskmanage",
},
{
name: "任务管理",
path: "/task/taskmanage",
component: "./task/Taskmanage",
},
{
name: "异常管理",
path: "/task/exceptionmanagement",
component: "./task/Exceptionmanagement",
},
{
component: "./404"
},
],
},
{
component: "./404",
},
],
},
{
component: "./404",
},
];
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}
{
"name": "system",
"private": true,
"author": "wuhao930406 <1148547900@qq.com>",
"scripts": {
"dev": "umi dev",
"build": "cross-env REACT_APP_ENV=prod umi build",
"postinstall": "umi setup",
"setup": "umi setup",
"start": "npm run dev"
},
"dependencies": {
"@ant-design/icons": "^5.1.4",
"@ant-design/pro-components": "^2.6.43",
"@react-three/drei": "^9.88.4",
"@react-three/fiber": "^8.14.6",
"@types/three": "^0.157.0",
"ahooks": "^3.7.7",
"antd": "^5.5.2",
"antd-img-crop": "^4.12.2",
"braft-editor": "^2.3.9",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.7",
"lodash": "^4.17.21",
"mitt": "^3.0.1",
"pinyin": "^3.1.0",
"react-activation": "^0.12.4",
"react-custom-scrollbars": "^4.2.1",
"react-resizable": "^3.0.5",
"react-reveal": "^1.2.2",
"swiper": "^11.0.5",
"techui-react-lite": "^0.0.6",
"three": "^0.157.0",
"umi": "^4.0.69",
"umi-plugin-keep-alive": "^0.0.1-beta.35",
"umi-request": "^1.4.0"
},
"devDependencies": {
"@types/react": "^18.0.33",
"@types/react-dom": "^18.0.11",
"@umijs/plugins": "^4.0.69",
"cross-env": "^7.0.3",
"typescript": "^5.0.3"
}
}
import React, { useState, useEffect } from "react";
import { autoFixContext } from "react-activation";
import jsxDevRuntime from "react/jsx-dev-runtime";
import jsxRuntime from "react/jsx-runtime";
import { AliveScope } from "react-activation";
import { history } from "umi";
import { message } from "antd";
import { queryCurrentUser, getMenu } from "./services/login";
import defaultSettings from "../config/defaultSettings";
let loginpath = '/user/login';
export function rootContainer(container) {
return React.createElement(AliveScope, null, container);
}
autoFixContext(
[jsxRuntime, "jsx", "jsxs", "jsxDEV"],
[jsxDevRuntime, "jsx", "jsxs", "jsxDEV"]
);
export async function getInitialState() {
let token = localStorage.getItem("TAIANTOKEN");
const fetchUserInfo = async () => {
try {
const res = await queryCurrentUser();
return res?.data ?? {};
} catch (error) {
history.push(loginpath);
}
return undefined;
}; // 如果是登录页面,不执行
const getmenuData = async () => {
try {
const res = await getMenu();
return res?.data ?? {};
} catch (error) {
message.error('接口失败');
}
return undefined;
}; // 如果是登录页面,不执行
if (history.location.pathname !== loginpath && token) {
const currentUserData = await fetchUserInfo();
let menuData;
if (currentUserData?.data?.userName) {
menuData = await getmenuData();
}
return {
fetchUserInfo,
currentUser: currentUserData?.data,
routesMenu: menuData?.userHavePermList,
buttonPerm:menuData?.buttonPerm,
getmenuData,
routes: {},
};
}
return {
fetchUserInfo,
getmenuData
};
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
import React, { Component } from "react";
import { Resizable } from "react-resizable";
function Resizecell({ onResize, onResizeStop, width, onClick, ...restProps }) {
return (
<Resizable
width={width??1}
height={0}
onResize={onResize}
onResizeStop={onResizeStop}
>
<th {...restProps} />
</Resizable>
);
}
export default Resizecell;
/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable react/jsx-key */
import { Card, Tabs, Upload, message, Modal } from "antd";
import { useMemo } from "react";
import PremButton from "../PremButton"; //权限判断fn
import Mtable from "./mtable";
import { ImportOutlined } from "@ant-design/icons";
function isString(obj) {
return obj.constructor === String ? true : false;
}
export default (props) => {
// 导入配置
const token =
localStorage.getItem("TAIANTOKEN") ?? "3ae582cbf2b141d94de2da1b59d2701f";
const importProps = {
...props?.importconfig,
action: "/pl" + props?.importconfig?.action,
showUploadList: false,
name: "excelfile",
headers: {
// 'Content-Type': 'multipart/form-data',
token: token,
},
onChange(info) {
if (info.file.status !== "uploading") {
console.log(info.file, info.fileList);
}
if (info.file.status === "done") {
if (info.file.response?.code == "0000") {
if (info.file.response?.data?.dataList?.length !== 0) {
Modal.warning({
title: "导入失败",
width: 1000,
okText: "知道了",
content: (
<div>
<Mtable
dataSource={info?.file?.response?.data?.dataList}
columns={[
{
title: "行数",
dataIndex: "name",
key: "name",
search: false,
},
{
title: "错误信息",
dataIndex: "error",
key: "error",
search: false,
},
]}
/>
</div>
),
});
return;
}
message.success(`文件导入成功!`);
props?.importconfig.reload();
} else {
message.warning(`${info.file.response?.msg}`);
if (info.file.response?.code == "7777") {
Modal.warning({
title: "导入失败",
width: 1000,
okText: "知道了",
content: (
<div>
<Mtable
dataSource={info?.file?.response?.data?.dataList}
columns={[
{
title: "行数",
dataIndex: "name",
key: "name",
search: false,
},
{
title: "错误信息",
dataIndex: "error",
key: "error",
search: false,
},
]}
/>
</div>
),
});
}
}
} else if (info.file.status === "error") {
message.error(`${info.file.name} file upload failed.`);
}
},
};
let { childposition } = props;
childposition = childposition ?? "left";
const actionbtn = {
add: (
<PremButton {...props?.addconfig}>
{props?.addconfig?.name || "新增"}
</PremButton>
),
export: (
<PremButton {...props?.exportconfig}>
{props?.exportconfig?.name || "导出"}
</PremButton>
),
import: (
<Upload {...importProps}>
<PremButton
btn={{
icon: <ImportOutlined />,
}}
>
导入
</PremButton>
</Upload>
),
download: (
<PremButton {...props?.downloadconfig}>
{props?.downloadconfig?.name || "下载模板"}
</PremButton>
),
custom: (
<PremButton {...props?.customconfig}>
{props?.customconfig?.name || "自定义"}
</PremButton>
),
};
//右上角 pageextra 类型 1.reactDom 2.string 以逗号隔开 为none时不显示
const renderextra = () => {
if (props.pageextra && !isString(props.pageextra)) {
if (typeof props?.pageextra == "function") {
return props.pageextra?.();
} else {
return props.pageextra;
}
} else if (props.pageextra === "none") {
return <div style={{ height: 28, width: 64 }} />;
} else if (props.pageextra) {
let strarr = props.pageextra ? props.pageextra.split(",") : ["add"];
return strarr.map((it, i) => {
return (
<div key={i} style={{ marginRight: i == strarr.length - 1 ? 0 : 6 }}>
{actionbtn[it]}
</div>
);
});
}
};
const items = useMemo(() => {
if (props.tabList) {
return props.tabList.map((it) => {
return {
label: it.tab,
key: it.key,
children: (
<>
<div style={{ display: "flex", width: "100%" }}>
{(props.childposition == "left" || !props.childposition) &&
props.children}
<div
style={{
flex: 1,
overflow: "hidden",
paddingLeft: `${
props.childposition == "left" ? "15px" : "0"
}`,
}}
>
{props.childposition == "top" && props.children}
<Mtable
{...props}
iscurrent={props?.activeTabKey == it.key}
/>
</div>
{(props.childposition == "right" || !props.childposition) &&
props.children}
</div>
{props.childposition == "bottom" && props.children}
</>
),
};
});
}
}, [props.tabList, props.extraparams]);
return (
<div className="diycard">
{props.withCard === false ? (
<>
<div style={{ display: "flex", width: "100%" }}>
{(props.childposition == "left" || !props.childposition) &&
props.children}
<div style={{ flex: 1, width: "100%" }}>
{props.childposition == "top" && props.children}
<Mtable {...props} />
</div>
{(props.childposition == "right" || !props.childposition) &&
props.children}
</div>
{props.childposition == "bottom" && props.children}
</>
) : !props.tabList ? (
<Card
bordered={props.bordered === false ? false : true}
style={{ height: "100%" }}
title={props.pagetitle}
extra={<div className="center">{renderextra()}</div>}
activeTabKey={props.activeTabKey}
tabList={props.tabList}
onTabChange={props.onTabChange}
>
<div style={{ display: "flex", width: "100%" }}>
{(props.childposition == "left" || !props.childposition) &&
props.children}
<div
style={{
flex: 1,
overflow: "hidden",
paddingLeft: `${props.childposition == "left" ? "15px" : "0"}`,
}}
>
{props.childposition == "top" && props.children}
<Mtable {...props} />
</div>
{(props.childposition == "right" || !props.childposition) &&
props.children}
</div>
{props.childposition == "bottom" && props.children}
</Card>
) : (
<div className="tabstable">
<div
style={{
display: "flex",
justifyContent: "space-between",
padding: "16px 20px 0",
}}
>
<div style={{ fontSize: 16, fontWeight: 600 }}>
{props.pagetitle}
</div>
<div style={{ display: "flex", flexDirection: "row" }}>
{renderextra()}
</div>
</div>
<Tabs
className="autoTableTabs"
items={items}
onChange={props.onTabChange}
destroyInactiveTabPane
activeKey={props.activeTabKey}
/>
</div>
)}
</div>
);
};
This diff is collapsed.
/* eslint-disable react-hooks/exhaustive-deps */
import { ProDescriptions } from '@ant-design/pro-components';
import React, { useMemo, useState } from 'react';
import { doFetch } from '@/utils/doFetch';
import styles from './index.less';
import { Col } from 'antd';
const { Item } = ProDescriptions;
function DetailPro(props) {
let { fields } = props;
const [curitem, setcuritem] = useState(props.detailData ?? {}); //全部数据
const dataProps = useMemo(() => {
if (props.detailData) {
setcuritem(props.detailData);
return { dataSource: props.detailData };
} else {
return {
request: async () => {
let res = await doFetch({ url: props.detailpath, params: props.params });
setcuritem(res?.data?.data ?? {});
return {
success: res?.code == '0000',
data: res?.data?.data ?? {},
};
},
};
}
}, [props.detailData]);
return (
<ProDescriptions column={3} {...dataProps} title={props.detailtitle}>
{fields
?.filter((it) => !it.hideInDescriptions && it.valueType != 'option')
?.map((it, i) => {
const dataIndexs =
!it?.render || it?.valueType == 'option'
? { dataIndex: it.dataIndex, valueType: it.valueType }
: {};
if (it.valueType == 'split') {
return (
<Item span={24} key={i}>
<div className='splittitle' style={{ borderWidth: i == 0 ? 0 : 1 }}>
{it.title}
</div>
</Item>
);
}
return (
<Item
span={it?.span ? it?.span : fields[i + 1]?.valueType == 'split' ? 3 : 1}
key={it.dataIndex}
label={it.title}
{...dataIndexs}
>
{it?.render ? it?.render?.(curitem[it.dataIndex], curitem) : ''}
</Item>
);
})}
</ProDescriptions>
);
}
export default DetailPro;
.title {
position: relative;
width: 100%;
padding-top: 8px;
padding-left: 12px;
font-weight: bolder;
&::before {
position: absolute;
top: 11px;
left: 0;
width: 3px;
height: 16px;
background-color: #2780ed;
border-radius: 4px;
content: '';
}
&::after {
position: absolute;
top: 18px;
right: 0px;
width: calc(100% - 160px);
height: 1px;
border-bottom: 1px dotted rgba(0, 0, 0, 0.1);
border-radius: 4px;
content: '';
}
}
import InitForm from '../InitForm';
import { Drawer } from 'antd';
import React, { useState, memo } from 'react';
import DetailPro from '../DetailPro';
import PropTypes from 'prop-types';
function DrawerPro(props) {
let pushSettingFlag = props.pushSettingFlag;
let newProps = { ...props };
delete newProps.children;
delete newProps.style;
const detailprops = {
...newProps,
detailpath: props.detailpath,
fields: props.fields,
detailData: props.detailData,
};
return (
<Drawer
maskClosable={false}
placement="right"
closable={true}
getContainer={false}
rootStyle={{ position: 'absolute', transform: 'translateX(0)', zIndex: 10 }}
width={'100%'}
destroyOnClose={true}
{...props}
>
{
props.open && (
props.val == 'only' ? (
props.children
) : props.val == 'detail' ? (
<DetailPro {...detailprops} />
) : props.val == 'detailaddon' ? (
<div>
<DetailPro {...detailprops} />
{props?.children}
</div>
) : (
<>
{props.childrenposition == 'top' && props.children}
<InitForm {...newProps} />
{props.childrenposition == 'bottom' && props.children}
</>
)
)
}
{pushSettingFlag ? (
<a
id="pushSettingBtn"
onClick={() => {
props.checkVariableOpen();
}}
>
查看变量
</a>
) : null}
</Drawer>
);
}
DrawerPro.propTypes = {
detailpath: PropTypes.string, //详情
params: PropTypes.object, //详情|表单编辑 参数
fields: PropTypes.array, //详情列表
detailData: PropTypes.object, //详情数据
};
export default DrawerPro;
import React from 'react';
const Filedetail = ({ files }) => {
return <div style={{ display: "flex", flexFlow: "row wrap", width: "100%" }}>
{
files && typeof (files) == "string" ?
<a href={files} download={files} style={{ margin: '0 20px 0 0', display: 'block' }}>{urlName ? urlName : "下载"}</a>
: files && Array.isArray(files) && files?.length ?
files?.map(el => {
return <a title={el.name} key={el.url} href={el.url} download={el.name} style={{ margin: '0 20px 0 0', display: 'block' }}>{el.name}</a>
})
:
"-"
}
</div>
}
export default Filedetail;
\ No newline at end of file
import { GithubOutlined } from "@ant-design/icons";
import { DefaultFooter } from "@ant-design/pro-components";
import React from "react";
const Footer = () => {
const defaultMessage = "江苏南高智能装备创新中心有限公司技术部出品";
const currentYear = new Date().getFullYear();
return (
<DefaultFooter
style={{
background: "none",
}}
copyright={`${currentYear} ${defaultMessage}`}
/>
);
};
export default Footer;
This diff is collapsed.
{
"id": "3865952",
"name": "utools",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "3745216",
"name": "文件夹",
"font_class": "openfile",
"unicode": "e612",
"unicode_decimal": 58898
},
{
"icon_id": "7684628",
"name": "exe",
"font_class": "exe",
"unicode": "e666",
"unicode_decimal": 58982
},
{
"icon_id": "17412612",
"name": "Rename-1",
"font_class": "rename",
"unicode": "e6c8",
"unicode_decimal": 59080
},
{
"icon_id": "15391377",
"name": "复制",
"font_class": "fuzhi",
"unicode": "e621",
"unicode_decimal": 58913
},
{
"icon_id": "18171229",
"name": "粘贴,移动,重叠",
"font_class": "paste-full",
"unicode": "ea31",
"unicode_decimal": 59953
},
{
"icon_id": "19148152",
"name": "删 除",
"font_class": "shanchu",
"unicode": "e6cd",
"unicode_decimal": 59085
},
{
"icon_id": "20517942",
"name": "剪切",
"font_class": "jianqie",
"unicode": "e62a",
"unicode_decimal": 58922
},
{
"icon_id": "11882924",
"name": "bg-unknownfile",
"font_class": "unknownfile",
"unicode": "e649",
"unicode_decimal": 58953
},
{
"icon_id": "23016910",
"name": "word-1",
"font_class": "word",
"unicode": "e601",
"unicode_decimal": 58881
},
{
"icon_id": "23016911",
"name": "div-1",
"font_class": "ml",
"unicode": "e602",
"unicode_decimal": 58882
},
{
"icon_id": "23016916",
"name": "txt-1",
"font_class": "txt",
"unicode": "e605",
"unicode_decimal": 58885
},
{
"icon_id": "23016917",
"name": "JAVA",
"font_class": "java",
"unicode": "e606",
"unicode_decimal": 58886
},
{
"icon_id": "23016918",
"name": "excel-1",
"font_class": "xlsx",
"unicode": "e607",
"unicode_decimal": 58887
},
{
"icon_id": "23016920",
"name": "DOCX",
"font_class": "doc",
"unicode": "e608",
"unicode_decimal": 58888
},
{
"icon_id": "23016921",
"name": "PPT",
"font_class": "ppt",
"unicode": "e60a",
"unicode_decimal": 58890
},
{
"icon_id": "23016922",
"name": "源文件-1",
"font_class": "origin",
"unicode": "e60b",
"unicode_decimal": 58891
},
{
"icon_id": "23016923",
"name": "PDF",
"font_class": "pdf",
"unicode": "e60d",
"unicode_decimal": 58893
},
{
"icon_id": "23016928",
"name": "zip-1",
"font_class": "zip",
"unicode": "e60e",
"unicode_decimal": 58894
},
{
"icon_id": "23016929",
"name": "MP3",
"font_class": "mp3",
"unicode": "e60f",
"unicode_decimal": 58895
},
{
"icon_id": "23016932",
"name": "MP4",
"font_class": "mp4",
"unicode": "e610",
"unicode_decimal": 58896
},
{
"icon_id": "23016934",
"name": "文件夹",
"font_class": "folder",
"unicode": "e611",
"unicode_decimal": 58897
},
{
"icon_id": "10341023",
"name": "公告",
"font_class": "gonggao",
"unicode": "e61c",
"unicode_decimal": 58908
},
{
"icon_id": "11741020",
"name": "List",
"font_class": "List",
"unicode": "e684",
"unicode_decimal": 59012
},
{
"icon_id": "8625053",
"name": "云盘",
"font_class": "yunpan",
"unicode": "e837",
"unicode_decimal": 59447
},
{
"icon_id": "9059911",
"name": "圈子管理",
"font_class": "dt",
"unicode": "e62e",
"unicode_decimal": 58926
},
{
"icon_id": "21717185",
"name": "fsux_图表_甘特图",
"font_class": "fsux_tubiao_gantetu",
"unicode": "e600",
"unicode_decimal": 58880
},
{
"icon_id": "18020153",
"name": "记录",
"font_class": "jilu",
"unicode": "e615",
"unicode_decimal": 58901
},
{
"icon_id": "33472831",
"name": "chatgpt",
"font_class": "a-chatgpt",
"unicode": "e604",
"unicode_decimal": 58884
},
{
"icon_id": "2742629",
"name": "点赞",
"font_class": "dianzan",
"unicode": "e668",
"unicode_decimal": 58984
},
{
"icon_id": "6337465",
"name": "笑脸",
"font_class": "xiaolian",
"unicode": "ec80",
"unicode_decimal": 60544
},
{
"icon_id": "27479864",
"name": "menu",
"font_class": "menu",
"unicode": "e623",
"unicode_decimal": 58915
},
{
"icon_id": "5712920",
"name": "统计",
"font_class": "tongji",
"unicode": "e61b",
"unicode_decimal": 58907
},
{
"icon_id": "705682",
"name": "拼图",
"font_class": "pintu",
"unicode": "e61e",
"unicode_decimal": 58910
},
{
"icon_id": "15025371",
"name": "bell",
"font_class": "bell",
"unicode": "e8e3",
"unicode_decimal": 59619
},
{
"icon_id": "8300922",
"name": "已完成",
"font_class": "yiwancheng",
"unicode": "e613",
"unicode_decimal": 58899
},
{
"icon_id": "24284929",
"name": "进行中-时间-倒计时-03",
"font_class": "jinhangzhong-shijian-daojishi-03",
"unicode": "e75c",
"unicode_decimal": 59228
},
{
"icon_id": "3513169",
"name": "未开始",
"font_class": "not_started",
"unicode": "e60c",
"unicode_decimal": 58892
},
{
"icon_id": "8293091",
"name": "线下商户推广",
"font_class": "xianxiashanghutuiguang",
"unicode": "e609",
"unicode_decimal": 58889
},
{
"icon_id": "14349780",
"name": "提交",
"font_class": "tijiao",
"unicode": "e75b",
"unicode_decimal": 59227
}
]
}
import { createFromIconfontCN } from '@ant-design/icons';
//import scriptUrl from '@/renderer/assets/font_source/iconfont';
// <IconFont type="icon-tuichu" />
import font from './font/iconfont'
const IconFont = createFromIconfontCN({
scriptUrl: '//at.alicdn.com/t/c/font_4106070_hu218e61s6.js',//font,
});
export default IconFont;
import { Image } from "antd";
const Imgdetail = ({ files, width, height }) => {
return <div style={{ display: "flex", flexFlow: "row wrap", width: "100%" }}>
{
files && typeof (files) == "string" ?
<Image style={{ marginRight: 15}} src={files} width={width ?? 40} height={height ?? 40}></Image>
: files && Array.isArray(files) && files?.length ?
files?.map(el => {
return <div style={{ marginRight: 15}} key={el?.uid} >
<Image src={el?.url} width={width ?? 40} height={height ?? 40} ></Image>
</div>
})
:
"-"
}
</div>
}
export default Imgdetail;
\ No newline at end of file
import { CopyOutlined } from '@ant-design/icons';
import { Input, Button, message, Divider } from 'antd';
import copy from 'copy-to-clipboard';
import { useState } from 'react';
const ColumnsTrans = () => {
const [requestMsg, setrequestMsg] = useState('');
const [newRequest, setnewRequest] = useState('');
const [borderColor, setborderColor] = useState(null);
const translateHandler = () => {
try {
let newString = JSON.parse(requestMsg);
// let newString = eval('('+requestMsg+')');
const newRequestArr = formatPrettier(newString);
setnewRequest(newRequestArr);
setborderColor('green');
} catch (error) {
message.error('“request”内容的格式不符合JSON字符串格式!');
setborderColor('red');
}
};
const formatPrettier = (jsonObj) => {
// debugger
// {
// title: '文本',
// key: 'text',
// dataIndex: 'id',
// },
let arr = [];
for (let key in jsonObj) {
if (key.toLowerCase() == 'id') continue;
const newObj = {
title: jsonObj[key],
key: key,
dataIndex: key,
};
arr = [...arr, newObj];
}
const newRequestString = JSON.stringify(arr)
.replace(/\[/g, '[\n\t')
.replace(/\]/g, ']')
.replace(/\,/g, ',\n\t')
.replace(/\{/g, '{\n\t')
.replace(/\}\,/g, '\n\t},')
.replace(/\}\]/g, '\n\t}\n]');
return newRequestString;
};
return (
<div>
<Divider orientation="left">Request</Divider>
<Input.TextArea
name="text"
placeholder="请输入Request内容,须符合JSON字符串格式"
allowClear={true}
value={requestMsg}
autoSize={{ minRows: 10 }}
onChange={(value) => {
let newValue = value?.target?.value;
setrequestMsg(newValue);
}}
style={{ borderColor: borderColor }}
/>
<Button type="primary" onClick={translateHandler} style={{ margin: 6 }}>
转换
</Button>
<Input.TextArea name="beautify" autoSize={{ minRows: 8, maxRows: 16 }} value={newRequest} />
<Button
style={{ margin: 6 }}
onClick={() => {
copy(newRequest);
message.success('已成功复制到剪切板!');
}}
>
复制
</Button>
</div>
);
};
export default ColumnsTrans;
This diff is collapsed.
/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable react-hooks/rules-of-hooks */
import React, { useEffect, useRef, useState, memo, useMemo } from 'react';
import { EditableProTable } from '@ant-design/pro-components';
import { Tooltip } from 'antd';
import { doFetch } from '@/utils/doFetch';
const EditTable = (props) => {
const {
formRef, //表单Ref
rowKey, // key
columns = [], //columns
style, //style
path, //接口地址
extraparams, //额外参数
pageSize, //修改默认pageSize
pagination, //分页设置
x, //横向滚动
refreshDep, //依赖刷新 (已废弃)
getDefaultSelected, //存在默认选中向上返回选中值
dataSource,
} = props;
let actionRefs = useRef(),
formRefs = formRef ?? useRef(),
ifspagination = pagination == 'false' || pagination === false,
[size, setsize] = useState('small');
//调用接口
const request = async (params, sort, filter) => {
if (!path)
return {
data: dataSource ?? [],
success: true,
total: dataSource?.length ?? 0,
};
// console.log('====================================');
// console.log(extraparams);
// console.log('====================================');
let newparams = {
...params,
...extraparams, //父组件传参
pageIndex: params.current,
pageSize: params.pageSize || pageSize,
};
delete newparams.current;
if (ifspagination) {
delete newparams.pageIndex;
delete newparams.pageSize;
}
const result = await doFetch({ url: path, params: newparams });
//分页结果
let data = result?.data?.page?.list,
success = true,
total = result?.data?.page?.total;
//不带分页获取结果
if (ifspagination || !data) {
data = result?.data?.dataList;
total = result?.data?.dataList?.length;
}
//存在默认选中向上返回选中值
getDefaultSelected && getDefaultSelected(result?.data);
return {
data,
success,
total,
};
};
let columncs = useMemo(() => {
return columns.map((item, index) => {
let it = { ...item };
let itemwidth = it.width ? it.width : 'auto';
let options = {};
if (it.valueType == 'select' || it.valueType == 'checkbox') {
if (Array.isArray(it.options)) {
options = {
fieldProps: {
...it?.fieldProps,
options: [...it.options],
},
};
} else if (it.options) {
options = {
request: async (params) => {
let list = await doFetch({ url: it?.options?.path, params: it?.options?.params });
return list.data.dataList;
},
};
}
}
if (it.valueType == 'option') {
options = {
key: 'option',
dataIndex: 'option',
fixed: 'right',
};
}
if (!it.render) {
options = {
...options,
render: (text, row) => {
return (
<Tooltip title={row[it.dataIndex]} placement="topLeft">
<span className="table-cell">{row[it.dataIndex] ?? '-'}</span>
</Tooltip>
);
},
};
}
options = {
...options,
width: itemwidth,
};
delete it.formItemProps;
return {
...it,
...options,
};
});
}, [columns]);
return (
<EditableProTable
{...props}
recordCreatorProps={false}
size={size}
params={{ ...extraparams }}
onSubmit={(params) => {
//console.log(params, 'onSubmit');
}}
onSizeChange={(size) => {
localStorage.setItem('size', size); //设置全局表格规格缓存
setsize(size);
}}
columns={columncs ?? []}
style={style || {}}
actionRef={actionRefs}
formRef={formRefs}
rowKey={rowKey ?? 'id'} //表格每行数据的key
dateFormatter="string"
request={request}
scroll={
x
? {
x: x,
}
: {}
}
pagination={
ifspagination
? false
: {
showTotal: (total, range) => <span>{total}</span>,
showQuickJumper: true,
showSizeChanger: true,
pageSizeOptions: [5, 10, 15, 30, 50, 100, 200],
defaultPageSize: pageSize || 15,
}
}
editable={{
type: 'multiple',
editableKeys: props?.rowSelection?.selectedRowKeys ?? [],
...props?.editable,
}}
search={{
filterType: 'light', //轻量模式
placement: 'bottomLeft',
}}
/>
);
};
export default memo(EditTable);
/* eslint-disable react-hooks/exhaustive-deps */
import 'braft-editor/dist/index.css';
import BraftEditor from 'braft-editor';
import React, { useState, useMemo, useEffect } from 'react';
import moment from 'moment';
export default function EditorItem({
value,
onChange,
height,
serverURL,
style,
bordered,
formRef,
curkey,
}) {
let UploadFn = (param) => {
const xhr = new XMLHttpRequest();
const fd = new FormData();
const successFn = (response) => {
// 假设服务端直接返回文件上传后的地址
// 上传成功后调用param.success并传入上传后的文件地址
param.success({
url: xhr.responseText ? JSON.parse(xhr.responseText).data?.dataList[0].url : null,
meta: {
id: moment(),
title: param.file.name,
alt: param.file.name,
loop: true, // 指定音视频是否循环播放
autoPlay: true, // 指定音视频是否自动播放
controls: true, // 指定音视频是否显示控制栏
poster: 'http://xxx/xx.png', // 指定视频播放器的封面
},
});
};
const progressFn = (event) => {
// 上传进度发生变化时调用param.progress
param.progress((event.loaded / event.total) * 100);
};
const errorFn = (response) => {
// 上传发生错误时调用param.error
param.error({
msg: '上传失败',
});
};
xhr.upload.addEventListener('progress', progressFn, false);
xhr.addEventListener('load', successFn, false);
xhr.addEventListener('error', errorFn, false);
xhr.addEventListener('abort', errorFn, false);
fd.append('file', param.file);
xhr.open(
'POST',
serverURL
? serverURL
: REACT_APP_URL + '/ngic-base-business/sysAttachment/uploadFile',
true,
);
xhr.send(fd);
};
return (
<div
style={{
...style,
border: bordered === false ? '#f9f9f9 solid 1px' : '#ddd solid 1px',
border: '#ddd solid 1px',
height: height ? height : 400,
overflow: 'hidden',
}}
>
<BraftEditor
media={{ uploadFn: UploadFn }}
value={BraftEditor.createEditorState(value)}
onChange={onChange}
/>
</div>
);
}
import { doFetch } from '@/utils/doFetch';
import React, { useState, useEffect, useForceUpdate } from 'react';
import AutoTable from '../../AutoTable/mtable';
import EditTable from '../EditTable';
function Expandables({ value = [], onChange, item }) {
const [allDatasource, setallDatasource] = useState({});
const [nvalue, setnvalue] = useState([]);
return (
<div>
<AutoTable
columns={item?.columns}
path={item?.path}
extraparams={item?.extraparams}
expandable={{
expandRowByClick: true,
onExpand: (expanded, record) => {
if (!expanded) return;
//找到value中当前展开的值
let curvalue = value
? value.filter((it) => it.lifePieceAccountId == record.id)?.[0]
: {};
//value中的list
let curvalist = curvalue?.lineStockUseList ?? [];
doFetch({ url: item.expandablePath, params: { lifePieceAccountId: record.id } }).then(
(res) => {
//展开接口返回的结果
let curDatasource = res?.data?.dataList ?? [];
//组合数据
let result = curDatasource?.map((it) => {
const itemval =
curvalist?.filter?.((item) => item.lineStockId == it.id)?.[0] ?? false;
if (itemval) {
it.operateNum = itemval.operateNum;
}
return it;
});
setallDatasource((s) => ({
...s,
[record.id]: result,
}));
},
);
},
expandedRowRender: (record) => {
let curvalue = value
? value.filter((it) => it.lifePieceAccountId == record.id)?.[0]
: {};
// console.log('nvalue', nvalue);
// console.log('record', record);
// console.log('allDatasource:', allDatasource);
// console.log(
// 'defaultvalue:',
// nvalue?.filter((it) => it.lifePieceAccountId == record.id)?.[0]?.lineStockUseList,
// );
return (
<>
<EditTable
key={nvalue
.filter((it) => it.lifePieceAccountId == record.id)?.[0]
?.lineStockUseList.map((it) => it.lineStockId)}
resizeable={false}
alwaysShowAlert={false}
tableAlertRender={false}
tableAlertOptionRender={false}
defaultValue={nvalue
?.filter((it) => it.lifePieceAccountId == record.id)?.[0]
?.lineStockUseList.map((i) => ({
id: i.lineStockId,
operateNum: i.operateNum,
}))}
columns={[
{
title: '线边库',
dataIndex: 'stockName',
search: false,
key: 'stockName',
editable: false,
},
{
title: '供应商编号',
dataIndex: 'supplierNo',
key: 'supplierNo',
search: false,
editable: false,
},
{
title: '供应商名称',
dataIndex: 'supplierName',
search: false,
key: 'supplierName',
editable: false,
},
{
title: '可用数量',
dataIndex: 'usedStock',
search: false,
key: 'usedStock',
editable: false,
},
{
title: (
<div>
更换数量 <span style={{ color: 'red' }}>* </span>
</div>
),
dataIndex: 'operateNum',
search: false,
key: 'operateNum',
valueType: 'digit',
fieldProps: {
precision: 3,
},
},
]}
dataSource={allDatasource[record.id]}
extraparams={allDatasource}
rowSelection={{
getCheckboxProps: (record) => ({
disabled: record.isAsh == '1',
}),
columnWidth: 44,
preserveSelectedRowKeys: true,
selectedRowKeys: curvalue?.lineStockUseList
? curvalue.lineStockUseList?.map?.((it) => it?.lineStockId)
: [],
onChange: async (selectedKeys, selectedRows) => {
// debugger;
const curval = curvalue?.lineStockUseList ?? [];
const rowkeylist = curval?.map?.((it) => it?.lineStockId);
const newValue = selectedRows?.map((its) => {
if (rowkeylist?.includes(its?.id)) {
return curval?.filter((it) => it?.lineStockId == its?.id)[0];
} else {
return {
lineStockId: its.id,
operateNum: its.operateNum,
};
}
});
let nvalue = value ? [...value] : [];
if (value && value?.some((it) => it.lifePieceAccountId == record?.id)) {
nvalue = value?.map((it, i) => {
if (it.lifePieceAccountId == record.id) {
it.lineStockUseList = newValue;
}
return it;
});
} else {
nvalue.push({
lifePieceAccountId: record?.id,
lineStockUseList: newValue,
});
}
// console.log('nvalue', nvalue);
nvalue = nvalue.filter((it) => it.lineStockUseList.length !== 0);
await onChange(nvalue);
await setnvalue(nvalue);
},
}}
editable={{
onValuesChange: async (rower, recordList) => {
const curval = curvalue?.lineStockUseList ?? [];
const newValue = curval?.map((its) => {
if (its?.lineStockId == rower?.id) {
return {
lineStockId: rower.id,
operateNum: rower.operateNum,
};
} else {
return its;
}
});
let nvalue = value ? [...value] : [];
if (value && value?.some((it) => it.lifePieceAccountId == record?.id)) {
nvalue = value?.map((it, i) => {
if (it.lifePieceAccountId == record.id) {
it.lineStockUseList = newValue;
}
return it;
});
} else {
nvalue.push({
lifePieceAccountId: record.id,
lineStockUseList: newValue,
});
}
// console.log('nvalue', nvalue);
await onChange(nvalue);
await setnvalue(nvalue);
},
}}
/>
</>
);
},
}}
/>
</div>
);
}
export default Expandables;
This diff is collapsed.
import { doFetch } from '@/utils/doFetch';
import { ProForm, ProFormDependency } from '@ant-design/pro-components';
import { Col, Input } from 'antd';
import { createElement, memo, useRef } from 'react';
import ColumnsTrans from './ColumnsTrans';
import FormItems from './FormItems';
import styles from './index.less';
function upperCase(str) {
const newStr = str.slice(0, 1).toUpperCase() + str.slice(1);
return newStr;
}
let FormRender = memo(({ fields = [], colProps, proformRef, defaultFormValue }) => {
return (
<>
{fields
.filter((it) => it.hideInForm !== true)
.map((item, index) => {
let key = item?.valueType ? upperCase(item?.valueType) : 'Input';
let { hideInForm } = item;
item.formItemProps = item.formItemProps ?? { rules: [] };
if (item.valueType == 'split') {
return (
<div key={index} className='splittitle' style={{ borderWidth: index == 0 ? 0 : 1 }}>
{item.title}
</div>
);
}
if (item?.valueType == 'nosubmit') {
return (
<Col key={index} {...(item.colProps ?? { span: 12 })} style={{ marginBottom: 24 }}>
<label style={{ marginBottom: 8, display: 'block' }}>{item?.title}</label>
<Input disabled value={item?.initialValue} />
</Col>
);
}
if (hideInForm && Object.keys(hideInForm)) {
return (
<ProFormDependency key={index} name={Object.keys(hideInForm)}>
{(params) => {
let ifs = true;
let res = Object.keys(hideInForm).map((its) => {
if (Array.isArray(hideInForm[its])) {
return !hideInForm[its].includes(params[its]);
} else {
let vals = hideInForm[its].reverse; //取反 即不存在当前数组中的
return vals.indexOf(params[its]) != -1;
}
});
ifs = res.includes(false);
if (ifs) {
return;
} else {
return createElement(FormItems[key], {
item: item,
colProps: colProps,
key: item.dataIndex,
formRef: proformRef,
});
}
}}
</ProFormDependency>
);
} else {
return createElement(FormItems[key], {
item: item,
colProps: colProps,
key: item.dataIndex,
formRef: proformRef,
defaultFormValue: defaultFormValue,
});
}
})}
</>
);
});
function InitForm(props) {
let {
className,
formRef,
onFinish = (vals) => {
//console.log(vals);
},
formKey,
params = {},
detailpath = '',
defaultFormValue = {},
detailFormat,
submitter,
fields,
colProps = { xs: 24, sm: 24, md: 12, lg: 12, xl: 12, xxl: 12 },
onValuesChange = (changedValues, allValues) => {
//console.log(changedValues, allValues);
},
val,
onReset,
style = {},
} = props;
// const { run } = useDebounceFn(onFinish, { wait: 400 });
let proformRef = useRef();
proformRef = formRef ?? proformRef;
function formartData(item, val) {
let formartValue = val;
if (
item?.valueType == 'uploadBtn' ||
item?.valueType == 'uploadImage' ||
item?.valueType == 'uploadDragger'
) {
let stepval =
val?.filter((it) => {
if (!it?.response) {
return it;
} else {
if (it?.response?.code == '0000') {
return it;
}
}
}) ?? [];
formartValue = stepval.map((it) => {
if (it.response) {
if (it.response.code != '0000') {
return undefined;
}
return it?.response?.data?.dataList?.[0] ?? undefined;
} else {
return it ? it : undefined;
}
});
}
return formartValue;
}
return fields?.length == 0 ? (
<ColumnsTrans />
) : (
<ProForm
style={{ overflow: 'hidden', ...style }}
formRef={proformRef}
onFinish={async (values) => {
let newAllvalues = {};
for (let i in values) {
newAllvalues[i] = formartData(
fields?.find((it) => it.key == i),
values[i],
);
}
await onFinish(newAllvalues);
}}
formKey={formKey ?? parseInt(Math.random() * 1000000)}
params={params}
submitter={submitter ?? true}
grid={true}
rowProps={{
gutter: 12,
}}
onReset={onReset}
request={async (params) => {
if (detailpath && val != 'add') {
let res = await doFetch({ url: detailpath, params });
//反填参数 格式化
const relationSupplierList = res?.data?.data?.relationSupplierList
? {
relationSupplierList: res?.data?.data?.relationSupplierList?.map?.((it, i) => {
return {
...it,
id: it?.supplierId,
};
}),
}
: {};
const supplierList = res?.data?.data?.supplierList
? {
supplierList: res?.data?.data?.supplierList?.map?.((it, i) => {
return {
...it,
id: it?.supplierId,
};
}),
}
: {};
let result = res?.data?.data;
if (result?.nrList) {
result.nrList = result?.nrList?.map((it) => {
it.sort = it.sort - 1;
return it;
});
}
return {
...defaultFormValue,
...(result ?? {}),
...relationSupplierList,
...supplierList,
};
} else {
// console.log({
// ...defaultFormValue,
// });
return {
...defaultFormValue,
};
}
}}
autoFocusFirstInput
onValuesChange={(changedValues, allValues) => {
onValuesChange?.(changedValues, allValues);
}}
className={className}
>
<FormRender
fields={fields?.filter((it) => it.valueType != 'option')}
colProps={colProps}
proformRef={proformRef}
defaultFormValue={defaultFormValue}
/>
</ProForm>
);
}
export default InitForm;
.title {
position: relative;
width: 100%;
margin-bottom: 8px;
padding-left: 16px;
color: #fff;
font-weight: bolder;
font-size: 14px;
&::before {
position: absolute;
top: 4px;
left: 7px;
width: 3px;
height: 16px;
background-color: rgb(58, 157, 250);
border-radius: 4px;
content: '';
}
&::after {
position: absolute;
top: 14px;
right: 0px;
width: calc(100% - 160px);
height: 1px;
border-bottom: 1px dotted rgba(0, 0, 0, 0.1);
border-radius: 4px;
content: '';
}
}
\ No newline at end of file
import React, { useState } from 'react';
import { Popconfirm, Button } from 'antd';
import { useModel } from 'umi';
function PremButton(props) {
const { initialState, setInitialState } = useModel('@@initialState');
const { children, btn, pop, access } = props;
let accesses = access ? ['havePrem'].includes(access) : true;
//配置按钮权限接口
return pop ? (
<Popconfirm {...pop} disabled={pop?.disabled || !accesses}>
<Button {...btn} disabled={btn?.disabled || !accesses}>
{children}
</Button>
</Popconfirm>
) : (
<Button {...btn} disabled={btn?.disabled || !accesses}>
{children}
</Button>
);
}
export default PremButton;
import React, { useState, useEffect } from "react";
import "./index.less";
function Switches({ value, onChange }) {
return (
<label className="switch">
<input
type="checkbox"
className="checkbox"
checked={value == "light"}
onChange={() => {
onChange(value == "light" ? "dark" : "light");
}}
/>
<span className="slider"></span>
</label>
);
}
export default Switches;
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment