Browse Source

:bug: 图片上传过程签名失效问题
:bug: 图片删除icon样式调整
:sparkles: 图片名称根据上传文件名自动生成
:sparkles: 选择模态框筛选条件变为编号优先
:bug: 选择模态框搜索后,已选内容丢失问题

zhanghe 6 years ago
parent
commit
8b2d3de43b

+ 30 - 2
src/components/AXTableSelector/MultipleSelectTable.js

@@ -22,8 +22,8 @@ export default class MultipleSelectTable extends Component {
   constructor(props) {
     super(props);
     this.state = {
-      selectedRows: props.selectedRows,
-      selectedRowKeys: props.selectedRowKeys,
+      selectedRows: props.selectedRows || [],
+      selectedRowKeys: props.selectedRowKeys || [],
     };
   }
 
@@ -70,18 +70,45 @@ export default class MultipleSelectTable extends Component {
   handleTableChange = (page, pageSize) => {
     this.props.onChange(page, pageSize);
   };
+  /**
+   * 响应行的点击动作
+   * @param record
+   */
+  handleOnRowClick = (record) => {
+    const { selectedRows, selectedRowKeys } = this.state;
+    const newSelectedRowKeys = [...selectedRowKeys];
+    const newSelectedRows = [...selectedRows];
+    const targetIndex = selectedRowKeys.indexOf(record.key);
+    if (targetIndex !== -1) {
+      newSelectedRowKeys.splice(targetIndex, 1);
+      newSelectedRows.splice(targetIndex, 1);
+    } else {
+      newSelectedRowKeys.push(record.key);
+      newSelectedRows.push(record);
+    }
+    this.setState({
+      selectedRowKeys: newSelectedRowKeys,
+      selectedRows: newSelectedRows,
+    });
+  };
 
   render() {
     const { loading, columns, dataSource, pagination, tableType } = this.props;
     const { selectedRowKeys } = this.state;
 
     const rowSelection = {
+      type: 'checkbox',
       selectedRowKeys,
       onChange: this.handleRowSelectChange,
       getCheckboxProps: record => ({
         disabled: record.disabled,
       }),
     };
+    const onRowClick = (record) => {
+      return {
+        onClick: () => this.handleOnRowClick(record),
+      };
+    };
 
     const renderTableFooter = (paginationProps) => {
       if (paginationProps) {
@@ -109,6 +136,7 @@ export default class MultipleSelectTable extends Component {
             footer={() => renderTableFooter(pagination)}
             rowKey={record => record.key}
             rowSelection={rowSelection}
+            onRow={onRowClick}
             onChange={this.handleTableChange}
             scroll={{ y: 350 }}
           />

+ 5 - 0
src/components/AXTableSelector/MultipleSelectTable.less

@@ -28,5 +28,10 @@
       height: 46px;
       padding: 5px;
     }
+    .ant-table-row {
+      &:hover {
+        cursor: pointer;
+      }
+    }
   }
 }

+ 1 - 7
src/components/AXTableSelector/Selector.js

@@ -16,18 +16,12 @@ export default class Selector extends PureComponent {
     const rows = addRowKey(props.selectedRows || []);
     const rowKeys = getRowKeys(rows || []);
     this.state = {
-      searchKey: 'name',
+      searchKey: 'code',
       searchValue: '',
       selectedRows: rows,
       selectedRowKeys: rowKeys,
     };
   }
-  componentWillReceiveProps(nextProps) {
-    this.setState({
-      selectedRows: addRowKey(nextProps.selectedRows),
-      selectedRowKeys: getRowKeys(addRowKey(nextProps.selectedRows) || []),
-    });
-  }
   /**
    * 选择搜索字段
    * @param value <code|name>

+ 16 - 23
src/components/AXTableSelector/SingleSelectTable.js

@@ -20,44 +20,36 @@ export default class SingleSelectTable extends Component {
     ]),
   };
   state = {
-    selectedRowKey: null,
+    selectedRowKeys: null,
   };
 
   handleRowClick = (record) => {
     this.setState({
-      selectedRowKey: record.key,
+      selectedRowKeys: record.key,
     });
     this.props.onSingleTransfer(record);
   };
+  handleRowSelectChange = (key) => {
+    this.setState({
+      selectedRowKeys: key,
+    });
+  };
   handleTableChange = (page, pageSize) => {
     this.props.onChange(page, pageSize);
   };
 
   render() {
     const { loading, columns, dataSource, pagination } = this.props;
-    const { selectedRowKey } = this.state;
+    const { selectedRowKeys } = this.state;
 
-    // 给首列加入单选按钮
-    const addColumnOnFirst = (cols) => {
-      const newColumns = [...cols];
-      newColumns.unshift({
-        key: '-1',
-        dataIndex: 'key',
-        width: 40,
-        render: (text) => {
-          return (
-            <Radio
-              key={text}
-              checked={selectedRowKey === text}
-            />
-          );
-        },
-      });
-      return newColumns;
+    const rowSelection = {
+      type: 'radio',
+      selectedRowKeys,
+      onChange: this.handleRowSelectChange,
     };
     const onRowClick = (record) => {
       return {
-        onClick: () => this.handleRowClick(record),
+        onClick: () => this.handleRowSelectChange(record.key),
       };
     };
     const renderTableFooter = (paginationProps) => {
@@ -77,12 +69,13 @@ export default class SingleSelectTable extends Component {
         bordered
         loading={loading}
         footer={() => renderTableFooter(pagination)}
-        columns={addColumnOnFirst(columns)}
+        columns={columns}
         dataSource={dataSource}
         pagination={false}
         rowKey={record => record.key}
-        onRow={onRowClick}
+        rowSelection={rowSelection}
         onChange={this.handleTableChange}
+        onRow={onRowClick}
         className={styles.table}
         scroll={{ y: 400 }}
       />

+ 1 - 1
src/components/AXUpload/index.js

@@ -177,7 +177,7 @@ class Uploader extends Component {
 
     return (
       <div>
-        <Upload.Dragger {...uploadProps}>
+        <Upload.Dragger {...uploadProps} className={styles.uploader}>
           <p className={styles.dragIcon}>
             <Icon type="inbox" />
           </p>

+ 7 - 0
src/components/AXUpload/index.less

@@ -1,5 +1,12 @@
 @import "~antd/lib/style/themes/default.less";
 
+.uploader {
+  :global(.anticon-cross) {
+    font-size: 20px !important;
+    color: #f5222d !important;
+    opacity: unset !important;
+  }
+}
 .dragIcon {
   margin-bottom: 10px !important;
   :global {

+ 3 - 3
src/routes/Resource/AudioBook/AudioBookList.js

@@ -114,11 +114,11 @@ export default class AudioBookListPage extends Component {
     }];
     const basicSearch = {
       keys: [{
-        name: '有声读物名称',
-        field: 'name',
-      }, {
         name: '有声读物编号',
         field: 'code',
+      }, {
+        name: '有声读物名称',
+        field: 'name',
       }],
     };
     const columns = [{

+ 19 - 15
src/routes/Resource/Picture/PictureEdit.js

@@ -29,6 +29,14 @@ function getFileObject(params) {
   const { format, url, path, name, size } = params;
   return { url, path, name, size, type: `image/${format}` };
 }
+function picNameFormat(name) {
+  if (!name) return name;
+  const separatorIndex = name.lastIndexOf('.');
+  if (separatorIndex !== -1) {
+    return name.substring(0, separatorIndex);
+  }
+  return name;
+}
 
 @Form.create()
 @connect(({ loading }) => ({
@@ -42,12 +50,8 @@ export default class PictureSingleUpload extends PureComponent {
     this.state = {
       fileList: [getFileObject(state)],
       code: state.code || '',
-      name: state.name || '',
     };
   }
-  handleNameInputChange = (e) => {
-    this.setState({ name: e.target.value });
-  };
   handleOnChangeEvent = (fileList) => {
     this.setState({ fileList });
     return fileList;
@@ -84,9 +88,9 @@ export default class PictureSingleUpload extends PureComponent {
   render() {
     const { form, submitting } = this.props;
     const { getFieldDecorator } = form;
-    const { fileList, code, name } = this.state;
+    const { fileList, code } = this.state;
     const firstPicture = fileList[0] || {};
-    const { type, size, path } = firstPicture;
+    const { type, size, path, name } = firstPicture;
 
     return (
       <PageHeaderLayout>
@@ -100,21 +104,13 @@ export default class PictureSingleUpload extends PureComponent {
                 <Input />
               )}
             </Form.Item>
-            <Form.Item label="图片名称" {...formItemLayout}>
-              {getFieldDecorator('name', {
-                rules: [{ required: true, message: '图片名称不能为空' }],
-                initialValue: name,
-              })(
-                <Input onChange={this.handleNameInputChange} />
-              )}
-            </Form.Item>
             <Form.Item label="图片上传" {...formItemLayout}>
               {getFieldDecorator('fileList', {
                 getValueFromEvent: this.handleOnChangeEvent,
               })(
                 <Uploader
                   forbidden={
-                    !((code && /^[a-zA-Z0-9|-]+$/ig.test(code) && name))
+                    !((code && /^[a-zA-Z0-9|-]+$/ig.test(code)))
                   }
                   fileCode={code}
                   fileList={fileList}
@@ -124,6 +120,14 @@ export default class PictureSingleUpload extends PureComponent {
                 />
               )}
             </Form.Item>
+            <Form.Item label="图片名称" {...formItemLayout}>
+              {getFieldDecorator('name', {
+                rules: [{ required: true, message: '图片名称不能为空' }],
+                initialValue: picNameFormat(name),
+              })(
+                <Input />
+              )}
+            </Form.Item>
             <Form.Item label="图片路径" {...formItemLayout}>
               {getFieldDecorator('path', {
                 initialValue: path,

+ 22 - 17
src/routes/Resource/Picture/PictureSingleUpload.js

@@ -23,6 +23,15 @@ const submitFormLayout = {
   },
 };
 
+function picNameFormat(name) {
+  if (!name) return name;
+  const separatorIndex = name.lastIndexOf('.');
+  if (separatorIndex !== -1) {
+    return name.substring(0, separatorIndex);
+  }
+  return name;
+}
+
 @Form.create()
 @connect(({ loading }) => ({
   submitting: loading.models.resource,
@@ -31,14 +40,10 @@ export default class PictureSingleUpload extends PureComponent {
   state = {
     fileList: [],
     code: null,
-    name: null,
   };
   handleCodeInputChange = (e) => {
     this.setState({ code: e.target.value });
   };
-  handleNameInputChange = (e) => {
-    this.setState({ name: e.target.value });
-  };
   handleOnChangeEvent = (fileList) => {
     this.setState({ fileList });
     return fileList;
@@ -76,9 +81,9 @@ export default class PictureSingleUpload extends PureComponent {
   render() {
     const { form, submitting } = this.props;
     const { getFieldDecorator } = form;
-    const { fileList, code, name } = this.state;
+    const { fileList, code } = this.state;
     const firstPicture = fileList[0] || {};
-    const { type, size, path } = firstPicture;
+    const { type, size, path, name } = firstPicture;
 
     return (
       <Form onSubmit={this.handlePageSubmit}>
@@ -88,9 +93,8 @@ export default class PictureSingleUpload extends PureComponent {
             type="warning"
             message={
               <Fragment>
-                <p>1.上传图片前应先填写符合规范的图片编号和名称,否则不能上传图片;</p>
-                <p>2.上传成功后会自动生成图片大小、格式、路径等信息,无需手动填写;</p>
-                <p>3.图片一旦创建完成,再次编辑时,图片编号不可修改。</p>
+                <p>1.上传图片前应先填写符合规范的图片编号,否则不能上传图片;</p>
+                <p>2.上传成功后会自动生成图片名称、大小、格式、路径等信息,无需手动填写;</p>
               </Fragment>
             }
           />
@@ -106,20 +110,13 @@ export default class PictureSingleUpload extends PureComponent {
             <Input onChange={this.handleCodeInputChange} />
           )}
         </Form.Item>
-        <Form.Item label="图片名称" hasFeedback {...formItemLayout}>
-          {getFieldDecorator('name', {
-            rules: [{ required: true, message: '名称不能为空!' }],
-          })(
-            <Input onChange={this.handleNameInputChange} />
-          )}
-        </Form.Item>
         <Form.Item label="图片上传" {...formItemLayout}>
           {getFieldDecorator('fileList', {
             getValueFromEvent: this.handleOnChangeEvent,
           })(
             <Uploader
               forbidden={
-                !((code && /^[a-zA-Z0-9|-]+$/ig.test(code) && name))
+                !((code && /^[a-zA-Z0-9|-]+$/ig.test(code)))
               }
               fileCode={code}
               fileList={fileList}
@@ -129,6 +126,14 @@ export default class PictureSingleUpload extends PureComponent {
             />
           )}
         </Form.Item>
+        <Form.Item label="图片名称" hasFeedback {...formItemLayout}>
+          {getFieldDecorator('name', {
+            rules: [{ required: true, message: '名称不能为空!' }],
+            initialValue: picNameFormat(name),
+          })(
+            <Input />
+          )}
+        </Form.Item>
         <Form.Item label="图片路径" {...formItemLayout}>
           {getFieldDecorator('path', {
             initialValue: path,

+ 3 - 3
src/routes/Resource/Video/VideoTableList.js

@@ -25,11 +25,11 @@ function VideoTableList({
   }];
   const basicSearch = {
     keys: [{
-      name: '视频名称',
-      field: 'name',
-    }, {
       name: '视频编号',
       field: 'code',
+    }, {
+      name: '视频名称',
+      field: 'name',
     }],
   };
   const columns = [{

+ 1 - 1
src/services/resource.js

@@ -32,7 +32,7 @@ export async function queryAudioBookResource(params) {
 
 export async function queryOssSignature(params) {
   const signature = getSignature();
-  const expireTime = Math.floor(((new Date()).getTime() / 1000) + 5).toString();
+  const expireTime = Math.floor(((new Date()).getTime() / 1000) + 15).toString();
 
   // 检查本地签名是否过期
   if (signature.expire >= expireTime) {