index.tsx 16.4 KB
Newer Older
1
import React from 'react';
2
import { Upload, Modal, message, Tabs, Result, Input, Collapse,Anchor  } from 'antd';
3 4 5 6
import { PlusOutlined, CheckCircleFilled } from '@ant-design/icons';
import ImgCrop from 'antd-img-crop';
import classnames from 'classnames';
import { UploadFile, UploadChangeParam, RcFile } from 'antd/lib/upload/interface';
7 8
import { uuid } from '@/utils/tools';
import { get, PUBLISH_SERVICE } from '@/services';
9
import { DownLoadFiles } from '@/services/common/api';
10
import styles from './index.less';
11
import { getImageBases } from '@/services/common/api';
12
import UploadContext from './context'
13
import _, { clone } from 'lodash'
14
const { Link } = Anchor;
15

16 17


18 19
const { TabPane } = Tabs;
const { Search } = Input;
20 21
// 维护图片分类映射
const wallCateName: any = {
张烨's avatar
张烨 committed
22
  icon: '图标',
23
  bg: '背景',
张烨's avatar
张烨 committed
24
  uploaded: '上传',
25
};
26
const tabNames: any = {
Maofei94's avatar
Maofei94 committed
27
  icon: 'icon图标',
Maofei94's avatar
Maofei94 committed
28
  androidMenu: '移动应用图标',
Maofei94's avatar
Maofei94 committed
29
  menuNew: '应用图标',
30
  logo: '项目logo',
31 32
  menu: '菜单图标',
  CityTemp: '用户上传',
涂伟's avatar
涂伟 committed
33 34 35
  bootAnimation: '开机动画',
  loginPageImage: '登录页',
  homePageImage: '主页焦点图',
张烨's avatar
张烨 committed
36
}
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

function getBase64(file: File | Blob) {
  return new Promise<string>((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result as string);
    reader.onerror = error => reject(error);
  });
}

interface PicturesWallType {
  fileList?: UploadFile<any>[];
  action?: string;
  headers?: any;
  withCredentials?: boolean;
  maxLen?: number;
  onChange?: (v: any) => void;
  cropRate?: number | boolean;
  isCrop?: boolean;
56
  type?: 'CityTemp' | 'icon' | 'androidMenu' | 'menuNew',
张烨's avatar
张烨 committed
57
  value?: string | string[],
张烨's avatar
张烨 committed
58
  uploadContext: any,
张烨's avatar
张烨 committed
59
  search: string,
张烨's avatar
张烨 committed
60
  actives: any,
Maofei94's avatar
Maofei94 committed
61
  picType: any,
62 63
  picSize: any,
  picStr: any,
64 65 66 67 68 69 70 71
}

class PicturesWall extends React.Component<PicturesWallType> {
  state = {
    previewVisible: false,
    previewImage: '',
    wallModalVisible: false,
    previewTitle: '',
张烨's avatar
张烨 committed
72
    imgBed: this.props.uploadContext?.imgBed || [],
73
    curSelectedImg: '',
74 75
    baseUrl: '',
    prevProps: {},
张烨's avatar
张烨 committed
76
    search: '',
张烨's avatar
张烨 committed
77
    actives: {},
张烨's avatar
张烨 committed
78 79 80 81 82
    fileList: this.props.value ? Array.isArray(this.props.value) ? this.props.value.map((v) => ({
      url: v,
      uid: uuid(8, 16),
      name: '熊猫运维中台系统',
      status: 'done',
83
    })) as UploadFile<any>[] : [{
张烨's avatar
张烨 committed
84 85 86 87
      url: this.props.value,
      uid: uuid(8, 16),
      name: '熊猫运维中台系统',
      status: 'done',
张烨's avatar
张烨 committed
88
    }] as UploadFile<any>[] : [],
89
  };
张烨's avatar
张烨 committed
90

91 92 93 94 95 96
  /**
   *  判断value是否更新,若更新则更新state.fileList
   *  判断imgBed是否更新,若更新则更新state.imgBed
   * @param props 
   * @param state 
   */
张烨's avatar
张烨 committed
97
  static getDerivedStateFromProps = (props, state) => {
98
    const { value, uploadContext = {} } = props;
张烨's avatar
张烨 committed
99
    const { imgBed, update } = uploadContext;
涂伟's avatar
涂伟 committed
100 101
    console.log(imgBed,'imgBedimgBedimgBedimgBed');
    
张烨's avatar
张烨 committed
102
    const fileList = state.fileList;
103
    const shouldUpdate = fileList.every(f => Array.isArray(value) ? !value.some(v => f.url === v) : f.url !== value)
104
    if (value !== state.prevProps.value && shouldUpdate) {
张烨's avatar
张烨 committed
105
      return {
张烨's avatar
张烨 committed
106
        prevProps: props,
107
        fileList: Array.isArray(value) ? value.map((v) => ({
张烨's avatar
张烨 committed
108 109 110 111
          url: v,
          uid: uuid(8, 16),
          name: '熊猫运维中台系统',
          status: 'done',
112
        })) as UploadFile<any>[] : value ? [{
张烨's avatar
张烨 committed
113
          url: value,
张烨's avatar
张烨 committed
114 115 116
          uid: uuid(8, 16),
          name: '熊猫运维中台系统',
          status: 'done',
117
        }] as UploadFile<any>[] : []
张烨's avatar
张烨 committed
118 119
      }
    }
120
    if (imgBed != state.prevProps.uploadContext?.imgBed) {
张烨's avatar
张烨 committed
121
      const activeKeys = {};
122 123 124 125 126 127 128 129 130 131 132 133
      const imgArr = JSON.parse(JSON.stringify(imgBed))
      imgArr.forEach(item => {
        if(item.fileUrls.length > 0) {
          item.child.unshift({
            moduleName: item.moduleName,
            fileUrls: item.fileUrls,
            child: [],
            baseUrl: item.baseUrl
          })
        }
        activeKeys[item.moduleName] = item.child.map(c => c.moduleName)
      });
张烨's avatar
张烨 committed
134 135
      return {
        prevProps: props,
张烨's avatar
张烨 committed
136 137
        imgBed,
        actives: activeKeys,
张烨's avatar
张烨 committed
138 139
      }
    }
张烨's avatar
张烨 committed
140 141 142
    return {
      prevProps: props
    };
张烨's avatar
张烨 committed
143 144
  }

145 146
  update = () => {
    if (this.props.value) {
张烨's avatar
张烨 committed
147
      this.setState({
148
        fileList: Array.isArray(this.props.value) ? this.props.value.map((v) => ({
张烨's avatar
张烨 committed
149 150 151 152
          url: v,
          uid: uuid(8, 16),
          name: '熊猫运维中台系统',
          status: 'done',
153
        })) as UploadFile<any>[] : [{
张烨's avatar
张烨 committed
154 155 156 157 158 159 160 161
          url: this.props.value,
          uid: uuid(8, 16),
          name: '熊猫运维中台系统',
          status: 'done',
        }] as UploadFile<any>[]
      })
    }
  }
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184

  handleCancel = () => this.setState({ previewVisible: false });

  handleModalCancel = () => this.setState({ wallModalVisible: false });

  handlePreview = async (file: UploadFile<any>) => {
    if (!file.url && !file.preview) {
      file.preview = await getBase64(file.originFileObj!);
    }

    this.setState({
      previewImage: file.url || file.preview,
      previewVisible: true,
      previewTitle: file.name || file.url!.substring(file.url!.lastIndexOf('/') + 1),
    });
  };

  handleWallSelect = (url: string) => {
    this.setState({
      wallModalVisible: true,
    });
  };

185
  handleImgSelected = (url: string, baseUrl: any) => {
186 187
    console.log(url,baseUrl);
    
188 189
    this.setState({
      curSelectedImg: url,
190
      baseUrl: baseUrl
191 192 193 194 195 196 197 198 199 200
    });
  };

  handleWallShow = () => {
    this.setState({
      wallModalVisible: true,
    });
  };

  handleModalOk = () => {
张烨's avatar
张烨 committed
201
    const { maxLen = 1 } = this.props;
202
    const { baseUrl, curSelectedImg } = this.state
203 204 205
    const fileList = [
      {
        uid: uuid(8, 16),
206
        name: '熊猫运维中台系统',
207
        status: 'done',
Maofei94's avatar
Maofei94 committed
208
        url: curSelectedImg,
209 210
      },
    ];
211
    if (!curSelectedImg) {
Maofei94's avatar
Maofei94 committed
212
      message.warn({
213 214
        duration: 2,
        content: '请先选择图片'
Maofei94's avatar
Maofei94 committed
215 216 217
      })
      return
    }
218 219 220 221
    if (curSelectedImg.includes('CityTemp')) {
      localStorage.setItem('pd-baseUrl', baseUrl)
    } else {
      localStorage.setItem('pd2-baseUrl', baseUrl)
Maofei94's avatar
Maofei94 committed
222 223
    }
    console.log(fileList[0].url)
224
    this.props.onChange && this.props.onChange(maxLen === 1 ? fileList[0].url.replace('civweb4\\', '') : fileList.map(f => f.url.replace('civweb4\\', '')));
225 226 227 228
    this.setState({ fileList, wallModalVisible: false });
  };

  handleChange = ({ file, fileList }: UploadChangeParam<UploadFile<any>>) => {
张烨's avatar
张烨 committed
229
    const { maxLen = 1, uploadContext } = this.props;
230 231 232
    this.setState({ fileList });
    if (file.status === 'done') {
      const files = fileList.map(item => {
张烨's avatar
张烨 committed
233
        const { status, name, thumbUrl } = item;
234 235 236 237
        let url = item.response && item.response.data || thumbUrl;
        if (url && (!url.includes('CityTemp') && !url.includes('图库'))) {
          url = 'CityTemp\\图库\\' + url
        } 
238
        return { uid: uuid(8, 16), name, status, url };
239
      });
240 241
      this.setState({ fileList: files })
      this.props.onChange && this.props.onChange(maxLen === 1 ? files[0].url : files.map(f => f.url));
张烨's avatar
张烨 committed
242
      uploadContext?.update && uploadContext.update()
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
    }
  };

  handleBeforeUpload = (file: RcFile) => {
    const isJpgOrPng =
      file.type === 'image/jpeg' ||
      file.type === 'image/png' ||
      file.type === 'image/jpg' ||
      file.type === 'image/gif';
    if (!isJpgOrPng) {
      message.error('只能上传格式为jpeg/png/gif的图片');
    }
    const isLt2M = file.size / 1024 / 1024 < 2;
    if (!isLt2M) {
      message.error('图片必须小于2MB!');
    }
259
    return isJpgOrPng && isLt2M || Upload.LIST_IGNORE;;
260 261
  };

张烨's avatar
张烨 committed
262 263 264 265 266 267 268 269
  // componentDidMount() {
  //   const { type = ''} = this.props;
  //   getImageBases(type).then(res => {
  //     if(res.code === 0){
  //       this.setState({imgBed: res.data})
  //     }
  //   })
  // }
270

271
  getImageUrl(path: string,previewFlag: boolean) {
272 273 274 275 276 277 278
        // return new Promise<string>((resolve, reject) => {
        //   DownLoadFiles({ module: '图库', filePath: path }).then(res=> {
        //     let reader = new FileReader();
        //       reader.readAsDataURL(res);
        //       reader.onload = () => resolve(reader.result as string);
        //   })
        // });
279 280 281 282 283 284 285 286 287
    if (path && path.indexOf('http') === 0) {
      return path
    }
    if (path && path.indexOf('data:') === 0) {
      return path
    }
    if (path && path.indexOf('assets') === 0) {
      return `${window.location.origin}/civweb4/${path}`.replace(/\\/g, '/')
    }
288 289 290 291
    
    if (path && (!path.includes('CityTemp') && !path.includes('图库'))) {
      path = 'CityTemp\\图库\\' + path
    } 
292 293 294
    if (previewFlag) {
      return path
    }
295 296
    
    return `/PandaOMS/OMS/FileCenter/DownLoadFiles?module=图库&filePath=${path}`
297
    // return `${window.location.origin}/${path}`.replace(/\\/g, '/')
298 299
  }

300
  getFileName(path: string) {
张烨's avatar
张烨 committed
301
    const match = path.match(/(?<=[\/\\])([^\\\/\.]*)(\.?\w*)$/)
302
    return match && match[1] || ''
张烨's avatar
张烨 committed
303 304
  }

305
  renderImgItem(url, baseUrl) {
张烨's avatar
张烨 committed
306
    const fileName = this.getFileName(url)
307
    const { curSelectedImg, search } = this.state;
张烨's avatar
张烨 committed
308
    return (
309
      <div
张烨's avatar
张烨 committed
310
        className={classnames({
311
          [styles.imgItem]: true,
张烨's avatar
张烨 committed
312
          [styles.hide]: !fileName.includes(search)
313
        })}
张烨's avatar
张烨 committed
314
        key={url}
315
        onClick={() => this.handleImgSelected(url, baseUrl)}>
张烨's avatar
张烨 committed
316 317 318 319 320
        <div
          className={classnames(
            curSelectedImg === url ? styles.seleted : '',
          )}
        >
321
          <img
张烨's avatar
张烨 committed
322 323
            className={classnames({
              [styles.svgGray]: /\.svg$/.test(url)
324 325 326
            })}
            src={this.getImageUrl(url)}
            title={url}
张烨's avatar
张烨 committed
327 328 329 330 331
            alt="熊猫运维中台系统" />
          <span className={styles.iconBtn}>
            <CheckCircleFilled />
          </span>
        </div>
332
        <span id={`#${curSelectedImg}`} title={fileName}>{fileName}</span>
张烨's avatar
张烨 committed
333 334 335 336
      </div>
    );
  }

337
  renderCollapse(module) {
张烨's avatar
张烨 committed
338
    const { Panel } = Collapse;
339 340 341 342 343 344 345
    const items = module.fileUrls.map(url => this.renderImgItem(url, module.baseUrl))
    return items.length > 0 && <Panel
      forceRender
      header={module.moduleName}
      key={module.moduleName}>
      {items}
    </Panel>
张烨's avatar
张烨 committed
346 347
  }

348 349
  handleCollapseChange(v, moduleName) {
    const activeKeys = { ...this.state.actives }
张烨's avatar
张烨 committed
350 351 352 353 354 355
    activeKeys[moduleName] = v;
    this.setState({
      actives: activeKeys
    })
  }

356 357 358 359 360 361 362 363
  render() {
    const {
      previewVisible,
      previewImage,
      fileList,
      previewTitle,
      wallModalVisible,
      imgBed,
张烨's avatar
张烨 committed
364
      actives,
365 366
      curSelectedImg,
    } = this.state;
367
    // console.log(imgBed,'imgBedddddddddddddddddddddd');
涂伟's avatar
涂伟 committed
368
    
369
    const {
370
      action = `${window.location.origin}${PUBLISH_SERVICE}/FileCenter/UploadSingleFile`,
371 372 373 374 375
      headers,
      withCredentials = true,
      maxLen = 1,
      cropRate = 375 / 158,
      isCrop,
Maofei94's avatar
Maofei94 committed
376
      picType,
377 378
    } = this.props;

379 380 381 382 383 384 385 386
    // 图片尺寸提示
    const picSize = {
      bootAnimation: '1125*2436',
      loginPageImage: '1132*1194',
      homePageImage: '1125*617'
    }
    const picStr = 'bootAnimation,loginPageImage,homePageImage'

387 388 389 390 391 392
    const uploadButton = (
      <div>
        <PlusOutlined />
        <div className="ant-upload-text">上传</div>
      </div>
    );
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
    const onSearch = (key) => {
      const bed = this.props.uploadContext.imgBed
      const nodes = _.cloneDeep(bed)

      for(const node of nodes){
        arrayTreeFilter(node,key)
      }
       
      console.log(nodes)
      this.setState({imgBed:nodes})

    }

    const arrayTreeFilter = (node,key) => {
      
      let reg = new RegExp(`/${key}/g`)
      
      for (const nodeItem of node.child) {
        if ( nodeItem.child.length < 1) {
         
          
            if(!reg.test(nodeItem.moduleName)){
              node.child.splice(nodeItem,1)
              console.log(nodeItem.moduleName,"--------------------移除图包-----------------")
            }
        }else{
          arrayTreeFilter(nodeItem,key);
        }
      }
      
    }
    
425 426 427 428 429 430 431 432 433

    return (
      <>
        {isCrop ? (
          <ImgCrop
            modalTitle="裁剪图片"
            modalOk="确定"
            modalCancel="取消"
            rotate={true}
张烨's avatar
张烨 committed
434
            aspect={cropRate as number}
435 436
          >
            <Upload
437
              fileList={fileList.map(f => ({ ...f, url: this.getImageUrl(f.url) }))}
438 439
              onPreview={this.handlePreview}
              onChange={this.handleChange}
440
              name="singleFile"
441 442 443 444 445
              listType="picture-card"
              className={styles.avatarUploader}
              action={action}
              withCredentials={withCredentials}
              headers={{
张烨's avatar
张烨 committed
446 447
                // 'x-requested-with': localStorage.getItem('user') || '',
                Authorization: 'Bearer ' + localStorage.getItem('token') || '',
448 449 450 451 452 453 454 455 456
                ...headers,
              }}
              beforeUpload={this.handleBeforeUpload}
            >
              {fileList.length >= maxLen ? null : uploadButton}
            </Upload>
          </ImgCrop>
        ) : (
          <Upload
457
            fileList={fileList.map(f => ({ ...f, url: this.getImageUrl(f.url) }))}
458 459
            onPreview={this.handlePreview}
            onChange={this.handleChange}
460
            name="singleFile"
461 462 463 464 465
            listType="picture-card"
            className={styles.avatarUploader}
            action={action}
            withCredentials={withCredentials}
            headers={{
张烨's avatar
张烨 committed
466 467
              // 'x-requested-with': localStorage.getItem('user') || '',
              Authorization: 'Bearer ' + localStorage.getItem('token') || '',
468 469 470 471 472 473 474 475
              ...headers,
            }}
            beforeUpload={this.handleBeforeUpload}
          >
            {fileList.length >= maxLen ? null : uploadButton}
          </Upload>
        )}
        <div className={styles.wallBtn} onClick={this.handleWallShow}>
476
          从图片库选择
477
        </div>
478 479 480
        <div className={styles.picTic} style={{display: picStr.includes(picType) && !fileList.length?'block':'none'}}>
          图片建议大小:{picSize[picType]}
        </div>
481 482
        <Modal
          visible={previewVisible}
邓超's avatar
邓超 committed
483
          // title={previewTitle}
484 485 486
          footer={null}
          onCancel={this.handleCancel}
        >
487
          <img alt="预览图片" className={styles.svgBg} style={{ width: '100%' }} src={this.getImageUrl(previewImage,true)} />
488 489 490 491 492 493
        </Modal>
        <Modal
          visible={wallModalVisible}
          title="图片库"
          okText="确定"
          cancelText="取消"
Maofei94's avatar
Maofei94 committed
494
          width={1080}
495 496
          onCancel={this.handleModalCancel}
          onOk={this.handleModalOk}
张烨's avatar
张烨 committed
497
          className={styles.modal}
498
        >
499
          <Input    
500 501 502 503
                    placeholder="搜索图库" 
                    className={styles.search} 
                    size="middle" 
                    value={this.state.search}
504
                    style={{marginLeft:'102px',width:'50%'}}
505 506
                    onChange={e => this.setState({search: e.target.value})} 
                    allowClear/>
507
          {/* <Search style ={{   width:'200px',margin: '10px 0 10px 100px'}} onSearch={onSearch} /> */}
邓超's avatar
邓超 committed
508
          <Tabs defaultActiveKey={imgBed[0]?.moduleName} tabPosition="left" >
509
            {imgBed.map((item, i) => {
510 511 512
              if (item.moduleName == picType || item.moduleName == 'CityTemp') {
                const child = [...item.child] || [];
                if (item.fileUrls.length > 0) {
513
                  child.unshift({
514 515 516 517 518 519 520
                    moduleName: item.moduleName,
                    fileUrls: item.fileUrls,
                    child: [],
                    baseUrl: item.baseUrl
                  })
                }
                return (
521 522
                  <TabPane tab={tabNames[item.moduleName] || item.moduleName} key={item.moduleName} style={{overflow:'hidden'}}> 
                    
523 524 525 526 527 528 529 530 531 532 533
                    <div className={styles.imgBox}>
                      <Collapse
                        bordered
                        activeKey={actives[item.moduleName]}
                        onChange={(v) => this.handleCollapseChange(v, item.moduleName)}>
                        {child.map(child => this.renderCollapse(child))}
                      </Collapse>
                    </div>
                  </TabPane>
                );
              }
534
            })}
Maofei94's avatar
Maofei94 committed
535
            {/* <TabPane tab="更多" key="more">
张烨's avatar
张烨 committed
536
              <Result status="500" title="温馨提示" subTitle="更多素材, 正在筹备中..." />
Maofei94's avatar
Maofei94 committed
537
            </TabPane> */}
538 539 540 541 542 543 544
          </Tabs>
        </Modal>
      </>
    );
  }
}

张烨's avatar
张烨 committed
545 546
const PicturesWallWrapper = (props: any) => {
  return <UploadContext.Consumer>
547
    {(uploadContext) => <PicturesWall {...props} uploadContext={uploadContext} />}
张烨's avatar
张烨 committed
548 549 550
  </UploadContext.Consumer>
}
export default PicturesWallWrapper;