| | |
| | | }) |
| | | } else { |
| | | this.setState({ |
| | | typeOptions: typeOptions |
| | | typeOptions: typeOptions, |
| | | orgcode: res.orgcode, |
| | | orgname: res.orgname, |
| | | }) |
| | | } |
| | | |
| | |
| | | charType: res.voucher_class, |
| | | charName: res.voucher_char, |
| | | charInt: res.voucher_char_int, |
| | | orgcode: res.orgcode, |
| | | orgname: res.orgname, |
| | | // orgcode: res.orgcode, |
| | | // orgname: res.orgname, |
| | | tbdata: fromJS(data).toJS(), |
| | | status: 'saved' |
| | | }) |
| | |
| | | } |
| | | |
| | | render() { |
| | | const { type, status, loading, config, typeOptions, charType, charInt, data, vouDate, username, remark, attachments, title, attachlist } = this.state |
| | | const { type, status, book, loading, config, orgcode, typeOptions, charType, charInt, data, vouDate, username, remark, attachments, title, attachlist } = this.state |
| | | |
| | | return ( |
| | | <div className="menu-voucher-wrap" style={config.style}> |
| | |
| | | </div> |
| | | <div className="voucher-affix"> |
| | | 附单据 <InputNumber precision={0} value={attachments || 0} autoComplete="off" onChange={this.changeAttach}/> 张 |
| | | <ResetAttach attachlist={attachlist} onChange={(vals) => this.setState({attachlist: vals})}/> |
| | | <ResetAttach config={config} book={book} orgcode={orgcode} attachlist={attachlist} onChange={(vals) => this.setState({attachlist: vals})}/> |
| | | <ResetRemark remark={remark} ID={config.uuid + 'remark'} onChange={(val) => this.setState({remark: val})}/> |
| | | </div> |
| | | </div> : null} |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import PropTypes from 'prop-types' |
| | | import { is, fromJS } from 'immutable' |
| | | import moment from 'moment' |
| | | import { Upload, Button, Progress, notification } from 'antd' |
| | | import { UploadOutlined } from '@ant-design/icons' |
| | | import SparkMD5 from 'spark-md5' |
| | | import Api from '@/api' |
| | | import './index.scss' |
| | | |
| | | class FileUpload extends Component { |
| | | static propTpyes = { |
| | | config: PropTypes.object, // 表单信息 |
| | | onChange: PropTypes.func, // 表单变化 |
| | | } |
| | | |
| | | state = { |
| | | percent: 0, |
| | | accept: '', |
| | | accepts: null, |
| | | maxFile: null, |
| | | showprogress: false, |
| | | maxSize: 0, |
| | | filelist: [] |
| | | } |
| | | |
| | | UNSAFE_componentWillMount () { |
| | | const { config } = this.props |
| | | |
| | | let filelist = [] |
| | | let accept = '' |
| | | let accepts = null |
| | | |
| | | this.setState({ |
| | | accept, |
| | | accepts, |
| | | filelist, |
| | | maxSize: config.maxSize || 0, |
| | | maxFile: config.maxfile |
| | | }) |
| | | } |
| | | |
| | | shouldComponentUpdate (nextProps, nextState) { |
| | | return !is(fromJS(this.state), fromJS(nextState)) |
| | | } |
| | | |
| | | onChange = ({ fileList }) => { |
| | | fileList = fileList.map(item => { |
| | | if (item.status === 'error' && /^<!DOCTYPE html>/.test(item.response)) { |
| | | item.response = '' |
| | | } |
| | | return item |
| | | }) |
| | | |
| | | this.setState({filelist: fileList}) |
| | | } |
| | | |
| | | onRemove = file => { |
| | | this.setState({filelist: []}) |
| | | |
| | | this.props.onChange('') |
| | | } |
| | | |
| | | onUpdate = (url, name) => { |
| | | let filelist = fromJS(this.state.filelist).toJS() |
| | | |
| | | if (filelist[0] && url) { |
| | | filelist[0].status = 'done' |
| | | filelist[0].response = url |
| | | } |
| | | |
| | | this.setState({filelist}) |
| | | this.props.onChange(url, name) |
| | | } |
| | | |
| | | onFail = (msg) => { |
| | | let filelist = this.state.filelist.map(item => { |
| | | if (!item.url && !item.response && !item.status) { |
| | | item.status = 'error' |
| | | } |
| | | return item |
| | | }) |
| | | |
| | | this.setState({filelist, showprogress: false, percent: 0}) |
| | | |
| | | notification.warning({ |
| | | top: 92, |
| | | message: msg || '文件上传失败!', |
| | | duration: 5 |
| | | }) |
| | | } |
| | | |
| | | shardupload = (param, name) => { |
| | | let form = new FormData() |
| | | |
| | | form.append('file', param.binary) |
| | | form.append('fileMd5', param.fileMd5) |
| | | form.append('shardingMd5', param.fileMd5) |
| | | form.append('baseDomain', window.GLOB.baseurl) |
| | | form.append('rootPath', 'Content/images/upload/') |
| | | form.append('fileName', param.fileName) |
| | | form.append('fileExt', param.fileType) |
| | | form.append('shardingCnt', 1) |
| | | form.append('shardingNo', 1) |
| | | form.append('LoginUID', sessionStorage.getItem('LoginUID') || '') |
| | | form.append('UserID', sessionStorage.getItem('UserID') || '') |
| | | |
| | | Api.getLargeFileUpload(form).then(res => { |
| | | if (res.status) { |
| | | if (res.urlPath) { |
| | | this.onUpdate(res.urlPath, name) |
| | | } else { |
| | | this.onFail() |
| | | } |
| | | this.setState({ |
| | | percent: 100 |
| | | }, () => { |
| | | setTimeout(() => { |
| | | this.setState({ |
| | | showprogress: false, |
| | | percent: 0 |
| | | }) |
| | | }, 200) |
| | | }) |
| | | } else { |
| | | this.onFail(res.message) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | getuuid = () => { |
| | | let uuid = [] |
| | | let _options = '0123456789abcdefghigklmnopqrstuv' |
| | | for (let i = 0; i < 19; i++) { |
| | | uuid.push(_options.substr(Math.floor(Math.random() * 0x20), 1)) |
| | | } |
| | | uuid = uuid.join('') |
| | | return uuid |
| | | } |
| | | |
| | | beforeUpload = (file) => { |
| | | const { accepts, maxSize } = this.state |
| | | |
| | | if (accepts && file.name) { |
| | | let pass = false |
| | | accepts.forEach(type => { |
| | | if (new RegExp(type + '$', 'ig').test(file.name)) { |
| | | pass = true |
| | | } |
| | | }) |
| | | |
| | | if (!pass) { |
| | | setTimeout(() => { |
| | | this.onFail('文件格式错误!') |
| | | }, 10) |
| | | return false |
| | | } |
| | | } |
| | | if (maxSize) { |
| | | let fileSize = file.size / 1024 / 1024 |
| | | |
| | | if (fileSize > maxSize) { |
| | | setTimeout(() => { |
| | | this.onFail(`文件大小不可超过${maxSize}M`) |
| | | }, 10) |
| | | return false |
| | | } |
| | | } |
| | | |
| | | this.setState({ |
| | | showprogress: true, |
| | | percent: 0 |
| | | }) |
| | | |
| | | // 兼容性的处理 |
| | | let spark = new SparkMD5.ArrayBuffer() // 对arrayBuffer数据进行md5加密,产生一个md5字符串 |
| | | let totalFileReader = new FileReader() // 用于计算出总文件的fileMd5 |
| | | let param = {} |
| | | |
| | | param.fileName = file.name.replace(/\.{1}[^.]*$/ig, '') // 文件名(去除后缀名) |
| | | param.fileType = file.name.replace(/^.*\.{1}/ig, '') // 文件类型 |
| | | |
| | | if (!/^[A-Za-z0-9]+$/.test(param.fileName)) { // 文件名称含有英文及数字之外字符时,名称系统生成 |
| | | param.fileName = moment().format('YYYYMMDDHHmmss') + this.getuuid() |
| | | } |
| | | |
| | | totalFileReader.readAsArrayBuffer(file) |
| | | totalFileReader.onload = (e) => { // 对整个totalFile生成md5 |
| | | spark.append(e.target.result) |
| | | param.fileMd5 = spark.end() // 计算整个文件的fileMd5 |
| | | param.binary = file |
| | | |
| | | let _param = new FormData() |
| | | _param.append('fileMd5', param.fileMd5) |
| | | |
| | | Api.getFilePreUpload(_param).then(res => { |
| | | if (res.status && res.urlPath) { |
| | | this.onUpdate(res.urlPath, file.name) |
| | | this.setState({ |
| | | percent: 100 |
| | | }, () => { |
| | | setTimeout(() => { |
| | | this.setState({ |
| | | showprogress: false, |
| | | percent: 0 |
| | | }) |
| | | }, 200) |
| | | }) |
| | | } else { |
| | | this.shardupload(param, file.name) |
| | | } |
| | | }) |
| | | } |
| | | |
| | | totalFileReader.onerror = () => { |
| | | this.onFail('文件读取失败!') |
| | | } |
| | | |
| | | return false |
| | | } |
| | | |
| | | /** |
| | | * @description 组件销毁,清除state更新 |
| | | */ |
| | | componentWillUnmount () { |
| | | this.setState = () => { |
| | | return |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { showprogress, percent, filelist, accept } = this.state |
| | | |
| | | let uploadable = 'attach-form-container ' |
| | | |
| | | if (filelist.length >= 1) { |
| | | uploadable += 'limit-fileupload' |
| | | } |
| | | |
| | | const props = { |
| | | name: 'file', |
| | | disabled: showprogress, |
| | | listType: 'text', |
| | | fileList: filelist, |
| | | action: null, |
| | | accept: accept, |
| | | method: 'post', |
| | | multiple: false, |
| | | onChange: this.onChange, |
| | | onRemove: this.onRemove, |
| | | beforeUpload: this.beforeUpload, |
| | | className: uploadable |
| | | } |
| | | |
| | | return ( |
| | | <Upload {...props}> |
| | | <Button> |
| | | <UploadOutlined /> 点击上传 |
| | | </Button> |
| | | {showprogress ? <Progress percent={percent} size="small" /> : null} |
| | | </Upload> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default FileUpload |
New file |
| | |
| | | .attach-form-container { |
| | | .ant-progress-small.ant-progress-line { |
| | | position: absolute; |
| | | bottom: -20px; |
| | | left: 0px; |
| | | } |
| | | a[href^="data"] { |
| | | pointer-events: none; |
| | | .anticon-eye-o { |
| | | display: none; |
| | | } |
| | | } |
| | | } |
| | | .attach-form-container.limit-fileupload { |
| | | > .ant-upload { |
| | | display: inline; |
| | | >.ant-upload { |
| | | >input { |
| | | display: none; |
| | | } |
| | | >button { |
| | | display: none; |
| | | } |
| | | } |
| | | } |
| | | > .ant-upload-select-picture-card { |
| | | display: none; |
| | | } |
| | | } |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | import { Form, Input, Select, Radio, Col } from 'antd' |
| | | |
| | | import MKFileUpload from './fileupload' |
| | | |
| | | const { TextArea } = Input |
| | | |
| | | class AddAttach extends Component { |
| | | state = { |
| | | f_method: 'upload', |
| | | } |
| | | |
| | | handleConfirm = () => { |
| | | const { files } = this.props |
| | | |
| | | return new Promise((resolve, reject) => { |
| | | this.props.form.validateFieldsAndScroll((err, values) => { |
| | | if (err) return |
| | | |
| | | files.forEach(item => { |
| | | if (item.data_code === values.data_code) { |
| | | values.data_name = item.data_name |
| | | } |
| | | }) |
| | | |
| | | if (values.f_method === 'input') { |
| | | values.url = values.fileurl |
| | | } |
| | | |
| | | resolve(values) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | fileChange = (val, name) => { |
| | | if (name) { |
| | | this.props.form.setFieldsValue({attachments_title: name}) |
| | | } |
| | | } |
| | | |
| | | render() { |
| | | const { files } = this.props |
| | | const { getFieldDecorator } = this.props.form |
| | | const { f_method } = this.state |
| | | |
| | | const formItemLayout = { |
| | | labelCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 6 } |
| | | }, |
| | | wrapperCol: { |
| | | xs: { span: 24 }, |
| | | sm: { span: 16 } |
| | | } |
| | | } |
| | | |
| | | return ( |
| | | <Form {...formItemLayout} onKeyDown={this.onEnterSubmit}> |
| | | <Col span={12}> |
| | | <Form.Item label="文件夹"> |
| | | {getFieldDecorator('data_code', { |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: '请选择文件夹!' |
| | | } |
| | | ] |
| | | })(<Select> |
| | | {files.map((option, i) => |
| | | <Select.Option key={i} value={option.data_code}>{option.data_name}</Select.Option> |
| | | )} |
| | | </Select>)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={12}> |
| | | <Form.Item label="添加方式"> |
| | | {getFieldDecorator('f_method', { |
| | | initialValue: 'upload', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: '请选择添加方式!' |
| | | } |
| | | ] |
| | | })(<Radio.Group onChange={(e) => this.setState({f_method: e.target.value})}> |
| | | <Radio value="upload">上传</Radio> |
| | | <Radio value="input">输入</Radio> |
| | | </Radio.Group>)} |
| | | </Form.Item> |
| | | </Col> |
| | | {f_method === 'upload' ? <Col span={12}> |
| | | <Form.Item label="文件"> |
| | | {getFieldDecorator('url', { |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: '请添加文件!' |
| | | } |
| | | ] |
| | | })(<MKFileUpload config={{ |
| | | initval: '', |
| | | compress: 'false', |
| | | suffix: '', |
| | | maxfile: 1, |
| | | fileType: 'text' |
| | | }} onChange={(val, name) => this.fileChange(val, name)} />)} |
| | | </Form.Item> |
| | | </Col> : <Col span={24}> |
| | | <Form.Item label="文件地址"> |
| | | {getFieldDecorator('fileurl', { |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: '请输入文件地址!' |
| | | } |
| | | ] |
| | | })(<TextArea autoSize={{ minRows: 2 }}/>)} |
| | | </Form.Item> |
| | | </Col>} |
| | | <Col span={12}> |
| | | <Form.Item label="文件名"> |
| | | {getFieldDecorator('attachments_title', { |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | required: true, |
| | | message: '请输入文件名!' |
| | | }, |
| | | { |
| | | max: 50, |
| | | message: '最大长度为50位!' |
| | | } |
| | | ] |
| | | })(<Input />)} |
| | | </Form.Item> |
| | | </Col> |
| | | <Col span={24}> |
| | | <Form.Item label="备注"> |
| | | {getFieldDecorator('remark', { |
| | | initialValue: '', |
| | | rules: [ |
| | | { |
| | | max: 512, |
| | | message: '最大长度为512位!' |
| | | } |
| | | ] |
| | | })(<TextArea autoSize={{ minRows: 2 }}/>)} |
| | | </Form.Item> |
| | | </Col> |
| | | <div style={{clear: 'both'}}></div> |
| | | </Form> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Form.create()(AddAttach) |
New file |
| | |
| | | import React, {Component} from 'react' |
| | | |
| | | class Documents extends Component { |
| | | state = { |
| | | folders: [], |
| | | docs: [], |
| | | selectKey: [], |
| | | actFolder: '' |
| | | } |
| | | |
| | | UNSAFE_componentWillMount() { |
| | | const { documents } = this.props |
| | | |
| | | let folders = [] |
| | | let actFolder = documents[0].folder |
| | | let docs = [] |
| | | documents.forEach(item => { |
| | | folders.push(item.folder) |
| | | if (item.folder === actFolder) { |
| | | docs.push(item) |
| | | } |
| | | }) |
| | | |
| | | this.setState({selectKey: [], folders: Array.from(new Set(folders)), actFolder: actFolder, docs}) |
| | | } |
| | | |
| | | submit = () => { |
| | | this.props.onChange() |
| | | } |
| | | |
| | | checkfolder = (val) => { |
| | | const { documents } = this.props |
| | | const { actFolder } = this.state |
| | | |
| | | if (actFolder === val) return |
| | | |
| | | let docs = [] |
| | | documents.forEach(item => { |
| | | if (item.folder === val) { |
| | | docs.push(item) |
| | | } |
| | | }) |
| | | |
| | | this.setState({actFolder: val, selectKey: [], docs}) |
| | | } |
| | | |
| | | render() { |
| | | const { folders, docs, selectKey, actFolder } = this.state |
| | | |
| | | let checkAll = '' |
| | | if (selectKey.length > 0) { |
| | | checkAll = selectKey.length < docs.length ? ' half' : ' active' |
| | | } |
| | | |
| | | return ( |
| | | <div className="document-wrap"> |
| | | <div className="document-title"> |
| | | <div className="folder-box">文件夹</div> |
| | | <div className="folder"> |
| | | <span className={'square-select' + checkAll}></span> |
| | | <span>文件</span> |
| | | </div> |
| | | </div> |
| | | <div className="document-body"> |
| | | <div className="doc-name"> |
| | | {folders.map(folder => (<div className={actFolder === folder ? 'active' : ''} onClick={() => this.checkfolder(folder)} key={folder}>{folder}</div>))} |
| | | </div> |
| | | <div className="file-wrap"> |
| | | {docs.map(doc => { |
| | | return <div className="file-item" key={doc.id}> |
| | | <span className={'square-select' + (selectKey.indexOf(doc.id) > -1 ? ' active' : '')}></span> |
| | | <img src={doc.icon} alt=""/> |
| | | <span className="file-name">{doc.attachments_title}</span> |
| | | </div> |
| | | })} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | ) |
| | | } |
| | | } |
| | | |
| | | export default Documents |
| | |
| | | import React, {Component} from 'react' |
| | | import { fromJS } from 'immutable' |
| | | import { Button, Modal } from 'antd' |
| | | import { Button, Modal, notification } from 'antd' |
| | | import moment from 'moment' |
| | | import { DeleteOutlined } from '@ant-design/icons' |
| | | // import md5 from 'md5' |
| | | |
| | | import Api from '@/api' |
| | | import AddAttach from './addAttach' |
| | | import Documents from './documents' |
| | | import './index.scss' |
| | | |
| | | import wordImg from '@/assets/img/file-word-fill.png' |
| | | import excelImg from '@/assets/img/file-excel-fill.png' |
| | | import fileImg from '@/assets/img/file-fill.png' |
| | | import pdfImg from '@/assets/img/file-pdf-fill.png' |
| | | import pptImg from '@/assets/img/file-ppt-fill.png' |
| | | import picImg from '@/assets/img/picture-fill.png' |
| | | import rarImg from '@/assets/img/rar.png' |
| | | |
| | | class ResetAttach extends Component { |
| | | state = { |
| | | visible: false, |
| | | list: '' |
| | | upVisible: false, |
| | | docVisible: false, |
| | | files: [{data_code: 'ddd', data_name: '凭证'}], |
| | | list: [], |
| | | documents: [ |
| | | {id: '1223', folder: '凭证附件', icon: excelImg, attachments_title: '主表20230130173553.xlsx', attachments_url: 'http://主表20230130173553.xlsx'}, |
| | | {id: '1224', folder: '凭证附件', icon: excelImg, attachments_title: '主表2sdfsafjifjiji.xlsx', attachments_url: 'http://主表2sdfsafjifjiji.xlsx'}, |
| | | {id: '1225', folder: '凭证附件', icon: excelImg, attachments_title: '主表20230sjiejgiej.xlsx', attachments_url: 'http://主表20230sjiejgiej.xlsx'}, |
| | | {id: '1227', folder: '回执', icon: excelImg, attachments_title: '主表2023sdfrgtgfgd.xlsx', attachments_url: 'http://主表2023sdfrgtgfgd.xlsx'}, |
| | | ], |
| | | selectDocs: [] |
| | | } |
| | | |
| | | submit = () => { |
| | | this.setState({remark: '', visible: false}) |
| | | this.props.onChange() |
| | | this.setState({visible: false}) |
| | | this.props.onChange(this.state.list) |
| | | } |
| | | |
| | | trigger = () => { |
| | | const { attachlist } = this.props |
| | | let list = fromJS(attachlist).toJS() |
| | | list = list.map(item => { |
| | | item.icon = this.getIcon(item.attachments_url) |
| | | return item |
| | | }) |
| | | |
| | | this.setState({visible: true, list: fromJS(attachlist).toJS()}) |
| | | this.setState({visible: true, list: list}) |
| | | } |
| | | |
| | | triggerUpload = () => { |
| | | |
| | | upSubmit = () => { |
| | | const { config, book, orgcode } = this.props |
| | | |
| | | if (!book) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: '请选择账套!', |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | let ID = (() => { |
| | | let uuid = [] |
| | | let options = '0123456789abcdefghigklmnopqrstuv' |
| | | for (let i = 0; i < 19; i++) { |
| | | uuid.push(options.substr(Math.floor(Math.random() * 0x20), 1)) |
| | | } |
| | | uuid = moment().format('YYYYMMDDHHmmssSSS') + uuid.join('') |
| | | return uuid.toUpperCase() |
| | | })() |
| | | |
| | | this.formRef.handleConfirm().then(res => { |
| | | let param = { |
| | | func: 's_fcc_voucher_attachments_addupt', |
| | | data_code: res.data_code, |
| | | data_name: res.data_name, |
| | | id: ID, |
| | | orgcode: orgcode, |
| | | voucher_at_lp: '', |
| | | attachments_title: res.attachments_title, |
| | | f_method: res.f_method, |
| | | attachments_url: res.url, |
| | | remark: res.remark, |
| | | status: config.wrap.attachStatus !== 10 ? 0 : 10, |
| | | statusname: config.wrap.attachStatus !== 10 ? '待审核' : '已审核', |
| | | typename: config.name, |
| | | UserName: sessionStorage.getItem('User_Name') || '', |
| | | FullName: sessionStorage.getItem('Full_Name') || '', |
| | | BID: book.id |
| | | } |
| | | |
| | | Api.genericInterface(param).then(result => { |
| | | if (!result.status) { |
| | | notification.warning({ |
| | | top: 92, |
| | | message: result.message, |
| | | duration: 5 |
| | | }) |
| | | return |
| | | } |
| | | |
| | | let list = fromJS(this.state.list).toJS() |
| | | let item = { |
| | | id: ID, |
| | | data_code: res.data_code, |
| | | data_name: res.data_name, |
| | | attachments_title: res.attachments_title, |
| | | attachments_url: res.url |
| | | } |
| | | |
| | | item.icon = this.getIcon(res.url) |
| | | |
| | | list.push(item) |
| | | |
| | | this.setState({list: list}) |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | deleteFile = (id) => { |
| | | this.setState({list: this.state.list.filter(item => item.id !== id)}) |
| | | } |
| | | |
| | | getIcon = (url) => { |
| | | let type = 'file' |
| | | |
| | | if (/(.png|.jpg|.gif|.jpeg)$/i.test(url)) { |
| | | type = 'pic' |
| | | } else if (/(.doc|.docx)$/i.test(url)) { |
| | | type = 'word' |
| | | } else if (/(.xls|.xlsx)$/i.test(url)) { |
| | | type = 'excel' |
| | | } else if (/(.zip|.rar)$/i.test(url)) { |
| | | type = 'rar' |
| | | } else if (/.pdf$/i.test(url)) { |
| | | type = 'pdf' |
| | | } else if (/.pptx$/i.test(url)) { |
| | | type = 'ppt' |
| | | } |
| | | |
| | | let icon = fileImg |
| | | if (type === 'excel') { |
| | | icon = excelImg |
| | | } else if (type === 'word') { |
| | | icon = wordImg |
| | | } else if (type === 'pdf') { |
| | | icon = pdfImg |
| | | } else if (type === 'pic') { |
| | | icon = picImg |
| | | } else if (type === 'ppt') { |
| | | icon = pptImg |
| | | } else if (type === 'rar') { |
| | | icon = rarImg |
| | | } |
| | | |
| | | return icon |
| | | } |
| | | |
| | | docSubmit = () => { |
| | | |
| | | } |
| | | |
| | | render() { |
| | | const { visible } = this.state |
| | | const { visible, upVisible, docVisible, files, list, documents } = this.state |
| | | |
| | | return ( |
| | | <> |
| | |
| | | cancelText="" |
| | | destroyOnClose |
| | | > |
| | | <Button type="link" className="attach-type-btn" onClick={this.triggerUpload}>上传新文件</Button> |
| | | <Button type="link" className="attach-type-btn" onClick={this.trigger}>从会计电子档案选择</Button> |
| | | <Button type="link" className="attach-type-btn" onClick={() => this.setState({upVisible: true})}>上传新文件</Button> |
| | | <Button type="link" className="attach-type-btn" onClick={() => this.setState({docVisible: true, selectDocs: []})}>从会计电子档案选择</Button> |
| | | <div className="attach-selected-list"> |
| | | |
| | | |
| | | {list.map(item => { |
| | | return <div className="attach-item" key={item.id}> |
| | | <img src={item.icon} alt=""/> |
| | | <div className="attach-msg"> |
| | | <div>{item.attachments_title}</div> |
| | | <div>{item.data_name ? item.data_name + ' / ' : ''}{item.attachments_url}</div> |
| | | </div> |
| | | <div> |
| | | <DeleteOutlined onClick={() => this.deleteFile(item.id)}/> |
| | | </div> |
| | | </div> |
| | | })} |
| | | </div> |
| | | </Modal> |
| | | <Modal |
| | | title="添加附件" |
| | | wrapClassName="voucher-attach-add-wrap" |
| | | visible={upVisible} |
| | | width={700} |
| | | maskClosable={false} |
| | | onOk={this.upSubmit} |
| | | onCancel={() => { this.setState({ upVisible: false })}} |
| | | destroyOnClose |
| | | > |
| | | <AddAttach files={files} wrappedComponentRef={(inst) => this.formRef = inst} submit={this.upSubmit}/> |
| | | </Modal> |
| | | <Modal |
| | | title="电子档案" |
| | | wrapClassName="voucher-attach-document-wrap" |
| | | visible={docVisible} |
| | | width={700} |
| | | maskClosable={false} |
| | | onOk={this.docSubmit} |
| | | onCancel={() => { this.setState({ docVisible: false, selectDocs: [] })}} |
| | | destroyOnClose |
| | | > |
| | | {docVisible ? <Documents documents={documents} onChange={(vals) => this.setState({selectDocs: vals})}/> : null} |
| | | </Modal> |
| | | </> |
| | | ) |
| | | } |
| | |
| | | overflow-y: auto; |
| | | border: 1px solid #d8d8d8; |
| | | margin-top: 10px; |
| | | |
| | | .attach-item { |
| | | display: flex; |
| | | border-bottom: 1px solid #f1f1f1; |
| | | img { |
| | | width: 45px; |
| | | height: 45px; |
| | | padding: 9px; |
| | | margin-top: 5px; |
| | | } |
| | | .attach-msg { |
| | | flex: 1; |
| | | width: calc(100% - 95px); |
| | | padding: 5px 0px; |
| | | div { |
| | | color: #000000; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | } |
| | | .attach-msg + div { |
| | | width: 50px; |
| | | line-height: 45px; |
| | | margin-top: 5px; |
| | | text-align: center; |
| | | font-size: 16px; |
| | | cursor: pointer; |
| | | color: orangered; |
| | | } |
| | | } |
| | | } |
| | | .attach-selected-list::-webkit-scrollbar { |
| | | width: 7px; |
| | |
| | | background: rgba(0, 0, 0, 0); |
| | | } |
| | | } |
| | | } |
| | | .voucher-attach-add-wrap { |
| | | .ant-form { |
| | | > .ant-col { |
| | | float: none; |
| | | display: inline-block; |
| | | vertical-align: top; |
| | | } |
| | | > .ant-col-24 { |
| | | .ant-form-item-label { |
| | | width: 12.5%; |
| | | } |
| | | .ant-form-item-control-wrapper { |
| | | width: 84%; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | .voucher-attach-document-wrap { |
| | | .ant-modal-body { |
| | | padding: 15px; |
| | | } |
| | | .document-wrap { |
| | | .document-title { |
| | | display: flex; |
| | | background: #e8e8e8; |
| | | line-height: 38px; |
| | | border: 1px solid #d8d8d8; |
| | | border-bottom: none; |
| | | .folder-box { |
| | | width: 200px; |
| | | text-align: center; |
| | | border-right: 1px solid #d8d8d8; |
| | | } |
| | | .folder { |
| | | flex: 1; |
| | | .square-select { |
| | | top: 3px; |
| | | margin: 0 10px; |
| | | } |
| | | } |
| | | } |
| | | .document-body { |
| | | border: 1px solid #d8d8d8; |
| | | height: 300px; |
| | | display: flex; |
| | | .doc-name { |
| | | width: 200px; |
| | | text-align: center; |
| | | border-right: 1px solid #d8d8d8; |
| | | height: 100%; |
| | | overflow-y: auto; |
| | | div { |
| | | border-bottom: 1px solid #e8e8e8; |
| | | height: 40px; |
| | | line-height: 40px; |
| | | } |
| | | .active { |
| | | background: var(--mk-sys-color1); |
| | | } |
| | | } |
| | | .file-wrap { |
| | | flex: 1; |
| | | width: calc(100% - 200px); |
| | | height: 100%; |
| | | overflow-y: auto; |
| | | .file-item { |
| | | border-bottom: 1px solid #e8e8e8; |
| | | height: 40px; |
| | | line-height: 40px; |
| | | |
| | | .square-select { |
| | | top: 4px; |
| | | margin: 0 10px; |
| | | } |
| | | img { |
| | | width: 20px; |
| | | height: 20px; |
| | | margin-top: -2px; |
| | | margin-right: 5px; |
| | | } |
| | | .file-name { |
| | | display: inline-block; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | vertical-align: top; |
| | | width: calc(100% - 90px); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .doc-name::-webkit-scrollbar, .file-wrap::-webkit-scrollbar { |
| | | width: 7px; |
| | | } |
| | | .doc-name::-webkit-scrollbar-thumb, .file-wrap::-webkit-scrollbar-thumb { |
| | | border-radius: 5px; |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.13); |
| | | background: rgba(0, 0, 0, 0.13); |
| | | } |
| | | .doc-name::-webkit-scrollbar-track, .file-wrap::-webkit-scrollbar-track { |
| | | box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.05); |
| | | border-radius: 3px; |
| | | border: 1px solid rgba(0, 0, 0, 0.07); |
| | | background: rgba(0, 0, 0, 0); |
| | | } |
| | | |
| | | .square-select { |
| | | position: relative; |
| | | display: inline-block; |
| | | width: 16px; |
| | | height: 16px; |
| | | border: 1px solid #cccccc; |
| | | box-sizing: content-box; |
| | | margin: auto; |
| | | margin-right: 5px; |
| | | background-color: #ffffff; |
| | | transition: border-color 0.2s; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .square-select.active { |
| | | border-color: var(--mk-sys-color); |
| | | background: var(--mk-sys-color); |
| | | } |
| | | .square-select.half { |
| | | border-color: var(--mk-sys-color); |
| | | } |
| | | .square-select.half::before { |
| | | display: none; |
| | | } |
| | | .square-select.half::after { |
| | | position: absolute; |
| | | top: 4px; |
| | | left: 4px; |
| | | content: ' '; |
| | | display: block; |
| | | width: 8px; |
| | | height: 8px; |
| | | background: var(--mk-sys-color); |
| | | } |
| | | |
| | | .square-select::before { |
| | | position: relative; |
| | | top: 1px; |
| | | left: 6px; |
| | | content: ' '; |
| | | display: block; |
| | | width: 5px; |
| | | height: 11px; |
| | | border-style: solid; |
| | | border-width: 0 2px 2px 0; |
| | | border-color: #ffffff; |
| | | transform: rotate(45deg); |
| | | } |
| | | } |
| | | } |