Browse Source

费用报销模块

dev01 1 year ago
parent
commit
2af540918a

+ 6 - 0
js/component/dataDic.js

@@ -4221,6 +4221,12 @@ module.exports = {
     { label: '餐费', value: 4 },
     { label: '出差补贴', value: 5 },
     { label: '预借支', value: 6 },
+    { label: '油费', value: 7 },
+    { label: '招待费', value: 8 },
+    { label: '办公费', value: 9 },
+    { label: '福利费', value: 10 },
+    { label: '物业水电费', value: 11 },
+    { label: '打印费', value: 12 },
     { label: '其他', value: 0, }
   ],
 

+ 826 - 0
js/component/manageCenter/financialManage/account/accountDetaillist.jsx

@@ -0,0 +1,826 @@
+import React from "react";
+import $ from "jquery/src/ajax";
+import moment from "moment";
+import {
+  Button,
+  Form,
+  Input,
+  Spin,
+  Table,
+  Select,
+  message,
+  Tabs,
+  AutoComplete,
+  DatePicker,
+  Modal,
+} from "antd";
+import { ChooseList } from "../../order/orderNew/chooseList";
+import { ShowModal, getVehicleName, getTypeName, commonAdd, dealBigMoney } from "../../../tools"
+import ShowModalDiv from "@/showModal.jsx";
+import AccountDetails from "./accountDetails";
+import { accountType, typeLists, accountStatus } from "@/dataDic";
+
+const FormItem = Form.Item;
+const { RangePicker } = DatePicker;
+const { TabPane } = Tabs;
+
+const AccountDetaillist = React.createClass({
+
+  getInitialState() {
+    return {
+      showDetails: false,
+      data: {},
+      logvisible: false,
+      logdataSour: [],
+      visible: "",
+      reason: "",
+      checkData: {},
+      aname: "",
+      searchValues: {}, // 列表筛选条件
+      loading: false, //加载动画
+      changeList: undefined, // 更改后的表格显示数据
+      dataSource: [], // 列表数据
+      departmentArr: [],
+      pagination: {
+        defaultCurrent: 1,
+        defaultPageSize: 10,
+        showQuickJumper: true,
+        pageSize: 10,
+        onChange: function (page) {
+          this.loadData(page);
+        }.bind(this),
+        showTotal: function (total) {
+          return "共" + total + "条数据";
+        },
+      },
+      columns: [
+        {
+          title: "类型",
+          dataIndex: "type",
+          key: "type",
+          render: (text, record) => {
+            return (
+              <span>
+                {text == 0 ? record.typeOther : typeLists.find(item => item.value === text).label}
+              </span>
+            );
+          },
+        },
+        {
+          title: "报销金额(元)",
+          dataIndex: "amount",
+          key: "amount",
+        },
+        {
+          title: "实报金额(元)",
+          dataIndex: "realAmount",
+          key: "realAmount",
+        },
+        {
+          title: "报销编号",
+          dataIndex: "checkNo",
+          key: "checkNo",
+        },
+        {
+          title: "报销至订单",
+          dataIndex: "buyerName",
+          key: "buyerName",
+          render: (text, record) => {
+            return (
+              record.targetType == 0
+                ? <div>固定费用</div>
+                : <div>
+                  <div>{text || ""}</div>
+                  <div>{record.contractNo || ""}</div>
+                </div>
+            );
+          },
+        },
+        {
+          title: "报销至部门",
+          dataIndex: "applyDepName",
+          key: "applyDepName",
+          render: (text, record) => {
+            return (
+              <span>{record.targetType == 0 && text}</span>
+            );
+          },
+        },
+        {
+          title: "报销人",
+          dataIndex: "aname",
+          key: "aname",
+        },
+
+        {
+          title: "财务负责人",
+          dataIndex: "financeName",
+          key: "financeName",
+        },
+        {
+          title: "状态",
+          dataIndex: "status",
+          key: "status",
+          render: (text, record) => {
+            return (
+              <span style={{ color: accountStatus[text]["color"] }}>
+                {accountStatus[text]["label"]}
+              </span>
+            );
+          },
+        },
+        {
+          title: "报销公司/支付公司",
+          dataIndex: "payDepName",
+          key: "payDepName",
+          render: (text, record) => {
+            return (
+              <div>
+                <div>{record.applyDepName || ""}</div>
+                <div>{text || ""}</div>
+              </div>
+            );
+          },
+        },
+        {
+          title: "报销时间",
+          dataIndex: "createTimeStr",
+          key: "createTimeStr",
+        },
+        {
+          title: "操作",
+          dataIndex: "operate",
+          key: "operate",
+          render: (text, record) => {
+            return (
+              <div>
+                <div>
+                  {this.props.isOperate &&
+                    <Button type="primary"
+                      style={{ margin: 4 }}
+                      onClick={() => { this.download(record.attachmentUrl) }}
+                    >下载</Button>}
+                  {this.props.isOperate && record.examine == 1 &&
+                    <Button type="primary"
+                      style={{ margin: 4 }}
+                      onClick={(e) => {
+                        e.stopPropagation();
+                        this.setState({
+                          visible: "adopt",
+                          checkData: record,
+                        })
+                      }}
+                    >同意</Button>}
+                  {this.props.isOperate && record.examine == 1 &&
+                    <Button type="danger"
+                      style={{ margin: 4 }}
+                      onClick={(e) => {
+                        e.stopPropagation();
+                        this.setState({
+                          visible: "reject",
+                          checkData: record,
+                        })
+                      }}
+                    >驳回</Button>}
+                  {record.status != 0 && <Button
+                    style={{ margin: 4 }}
+                    onClick={() => {
+                      this.setState({
+                        logvisible: true
+                      })
+                      this.getLogData(record.mainId)
+                    }}>日志</Button>}
+                </div>
+              </div>
+            )
+          }
+        },
+      ],
+      logcolumns: [
+        {
+          title: "审核人",
+          dataIndex: "auditorName",
+          key: "auditorName"
+        },
+        {
+          title: "操作",
+          dataIndex: "status",
+          key: "status",
+          width: 120,
+          render: (text, record) => {
+            return (
+              <span style={{ color: ["#1D4FEA", "#34DE38", "#108EE9", "red", "#1D4FEA"][text] }}>
+                {["【发起】", "【通过】", "【完成】", "【驳回】", "【重新发起】"][text]}
+                {this.state.processStatus == record.processStatus && !record.id &&
+                  <span style={{ color: "#FFA500" }}>&nbsp;审核中...</span>}
+              </span>
+            );
+          },
+        },
+        {
+          title: "操作时间",
+          dataIndex: "createTimeStr",
+          key: "createTimeStr",
+          width: 88,
+        },
+        {
+          title: "备注",
+          dataIndex: "remarks",
+          key: "remarks",
+          render: (text, record) => {
+            return (
+              <div style={{ minWidth: 250 }}>{text}</div>
+            )
+          }
+        }
+      ],
+    };
+  },
+
+  componentWillMount() {
+    this.departmentList();
+    this.loadData();
+  },
+
+  // 列表接口
+  loadData(pageNo) {
+    const { searchValues, pagination } = this.state;
+    this.setState({
+      loading: true,
+    });
+    let datas = Object.assign(searchValues, {
+      pageNo: pageNo || 1,
+      pageSize: pagination.pageSize,
+      // expenseMain: 1,
+      // processStatus: this.props.isOperate ? 1 : 2,
+    });
+    $.ajax({
+      method: "get",
+      dataType: "json",
+      crossDomain: false,
+      url: globalConfig.context + "/api/admin/expenseAccount/detailsList",
+      data: datas,
+      success: function (data) {
+        ShowModal(this);
+        this.setState({
+          loading: false,
+        });
+        if (data.error && data.error.length === 0) {
+          if (data.data.list) {
+            pagination.current = data.data.pageNo;
+            pagination.total = data.data.totalCount;
+            if (data.data && data.data.list && !data.data.list.length) {
+              pagination.current = 0;
+              pagination.total = 0;
+            }
+            this.setState({
+              dataSource: data.data.list,
+              pagination: this.state.pagination,
+              pageNo: data.data.pageNo,
+              totalAmount: data.data.totalAmount,
+            });
+          } else {
+            this.setState({
+              dataSource: data.data,
+              pagination: false,
+            });
+          }
+        } else {
+          message.warning(data.error[0].message);
+        }
+      }.bind(this),
+    }).always(
+      function () {
+        this.setState({
+          loading: false,
+        });
+      }.bind(this)
+    );
+  },
+
+  // 日志
+  getLogData(eaid) {
+    $.ajax({
+      method: "get",
+      dataType: "json",
+      crossDomain: false,
+      url: globalConfig.context + "/api/admin/expenseAccount/log/list",
+      data: { eaid },
+      success: function (data) {
+        if (data.error.length === 0) {
+          this.setState({
+            logdataSour: data.data || []
+          });
+          this.isHere(data.data || [])
+        } else {
+          message.warning(data.error[0].message);
+        }
+      }.bind(this)
+    }).always(
+      function () {
+
+      }.bind(this)
+    );
+  },
+
+  // 
+  isHere(list = []) {
+    for (var i = 0; i < list.length; i++) {
+      if (!list[i].id) {
+        this.setState({
+          processStatus: list[i].processStatus
+        })
+        return
+      }
+    }
+  },
+
+  download(urls) {
+    if (!urls) {
+      message.error("暂无可下载的附件!");
+    } else {
+      let list = urls.split(',') || []
+      list.forEach(e => {
+        var aLink = document.createElement('a');
+        aLink.download = e;
+        aLink.href = globalConfig.context + `/open/download?fileName=${e}&delete=false`;
+        document.body.appendChild(aLink);
+        aLink.click();
+        document.body.removeChild(aLink);
+      });
+
+
+
+
+    }
+  },
+
+  departmentList() {
+    $.ajax({
+      method: "get",
+      dataType: "json",
+      crossDomain: false,
+      url: globalConfig.context + "/api/admin/organization/selectSuperId",
+      data: {},
+      success: function (data) {
+        let thedata = data.data;
+        let theArr = [];
+        if (!thedata) {
+          if (data.error && data.error.length) {
+            message.warning(data.error[0].message);
+          }
+        } else {
+          thedata.map(function (item, index) {
+            theArr.push({
+              key: index,
+              name: item.name,
+              id: item.id
+            });
+          });
+        }
+        this.setState({
+          departmentArr: theArr
+        });
+      }.bind(this)
+    }).always(
+      function () {
+
+      }.bind(this)
+    );
+  },
+
+  // 审核
+  toExamine(num) {
+    const { checkData, reason } = this.state
+    if (!reason) {
+      message.warning("请填写审核说明~");
+      return;
+    }
+    this.setState({
+      loading: true,
+    });
+    $.ajax({
+      method: "POST",
+      dataType: "json",
+      crossDomain: false,
+      url: globalConfig.context + "/api/admin/expenseAccount/examine",
+      data: {
+        id: checkData.id,
+        reason,
+        status: num,//1同意 3驳回
+      },
+    }).done(
+      function (data) {
+        if (!data.error.length) {
+          message.success("审核成功!");
+          this.setState({
+            visible: "",
+            reason: "",
+            showDetails: false,
+            checkData: {},
+          });
+          this.loadData()
+        } else {
+          message.warning(data.error[0].message);
+        }
+      }.bind(this)
+    );
+  },
+
+  tableRowClick(e) {
+    this.setState({
+      showDetails: true,
+      id: e.id,
+    })
+    // this.getDetails(e.id)
+
+  },
+
+  // 查询负责人
+  followUp(e) {
+    this.setState({
+      aname: e
+    });
+    $.ajax({
+      method: "get",
+      dataType: "json",
+      crossDomain: false,
+      url: globalConfig.context + "/api/admin/customer/listAdminByName",
+      data: {
+        adminName: e,
+      },
+      success: function (data) {
+        let thedata = data.data || [];
+        if (!thedata) {
+          if (data.error && data.error.length) {
+            message.warning(data.error[0].message);
+          }
+          thedata = {};
+        }
+        this.setState({
+          fjlist: thedata,
+        });
+      }.bind(this),
+    }).always(
+      function () {
+        this.setState({
+          loading: false,
+        });
+      }.bind(this)
+    );
+  },
+
+  // 选中负责人
+  selectF(value) {
+    const { searchValues, fjlist } = this.state;
+    const newdataSources = JSON.stringify(fjlist) == "{}" ? [] : fjlist;
+    this.setState({
+      searchValues: Object.assign(searchValues, {
+        aid: newdataSources.find((item) => item.name == value).id,
+      }),
+    });
+  },
+
+  // 搜索
+  search() {
+    this.loadData();
+  },
+
+  // 重置
+  reset() {
+    this.setState({
+      aname: "",
+      searchValues: JSON.parse(JSON.stringify({})),
+    }, () => {
+      this.loadData();
+    })
+  },
+
+  changeList(arr) {
+    const newArr = [];
+    this.state.columns.forEach((item) => {
+      arr.forEach((val) => {
+        if (val === item.title) {
+          newArr.push(item);
+        }
+      });
+    });
+    this.setState({
+      changeList: newArr,
+    });
+  },
+
+
+  render() {
+    const { TextArea } = Input
+    const { searchValues, visible, } = this.state
+    const formItemLayout = {
+      labelCol: { span: 5 },
+      wrapperCol: { span: 18 },
+    };
+    const dataSources = this.state.fjlist || [];
+    const options = dataSources.map((group) => (
+      <Select.Option key={group.id} value={group.name}>
+        {group.name}
+      </Select.Option>
+    ));
+
+    return (
+      <div className="user-content">
+        <ShowModalDiv ShowModal={this.state.showModal} />
+        <div className="content-title" style={{ marginBottom: 10 }}>
+          <span style={{ fontWeight: 900, fontSize: 16 }}>报销明细列表</span>
+        </div>
+        <Tabs defaultActiveKey="2" className="test">
+          <TabPane tab="搜索" key="2">
+            <div className="user-search" style={{ marginLeft: 10 }}>
+              <Input
+                placeholder="合同编号"
+                value={searchValues["contractNo"]
+                  ? searchValues["contractNo"]
+                  : ""}
+                onChange={(e) => {
+                  searchValues["contractNo"] = e.target.value;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              />
+              <Input
+                placeholder="客户名称"
+                value={searchValues["username"]
+                  ? searchValues["username"]
+                  : ""}
+                onChange={(e) => {
+                  searchValues["username"] = e.target.value;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              />
+              <Select
+                style={{ width: 140 }}
+                placeholder="报销类型"
+                value={searchValues["type"]
+                  ? searchValues["type"]
+                  : undefined}
+                onChange={(e) => {
+                  searchValues["type"] = e;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              >
+                <Option value="1">交通费</Option>
+                <Option value="2">住宿费</Option>
+                <Option value="3">市内车费</Option>
+                <Option value="4">餐费</Option>
+                <Option value="5">出差补贴</Option>
+                <Option value="6">预借支</Option>
+                <Option value="7">油费</Option>
+                <Option value="8">招待费</Option>
+                <Option value="9">办公费</Option>
+                <Option value="10">福利费</Option>
+                <Option value="11">物业水电费</Option>
+                <Option value="12">打印费</Option>
+                <Option value="0">其他</Option>
+              </Select>
+              <AutoComplete
+                className="certain-category-search"
+                dropdownClassName="certain-category-search-dropdown"
+                dropdownMatchSelectWidth={false}
+                style={{ width: 140 }}
+                dataSource={options}
+                placeholder="报销人"
+                value={this.state.aname}
+                onChange={this.followUp.bind(this)}
+                filterOption={true}
+                onSelect={this.selectF.bind(this)}
+              >
+                <Input />
+              </AutoComplete>
+              <Select
+                placeholder="所属部门"
+                style={{ width: 200, marginRight: 10 }}
+                value={searchValues["depId"]
+                  ? searchValues["depId"]
+                  : undefined}
+                onChange={e => {
+                  searchValues["depId"] = e;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              >
+                {this.state.departmentArr.map(function (item) {
+                  return <Select.Option key={item.id}>{item.name}</Select.Option>;
+                })}
+              </Select>
+              <Select
+                placeholder="申请部门"
+                style={{ width: 200, marginRight: 10 }}
+                value={searchValues["applyDep"]
+                  ? searchValues["applyDep"]
+                  : undefined}
+                onChange={e => {
+                  searchValues["applyDep"] = e;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              >
+                {this.state.departmentArr.map(function (item) {
+                  return <Select.Option key={item.id}>{item.name}</Select.Option>;
+                })}
+              </Select>
+              <Select
+                placeholder="支付部门"
+                style={{ width: 200, marginRight: 10 }}
+                value={searchValues["payDep"]
+                  ? searchValues["payDep"]
+                  : undefined}
+                onChange={e => {
+                  searchValues["payDep"] = e;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              >
+                {this.state.departmentArr.map(function (item) {
+                  return <Select.Option key={item.id}>{item.name}</Select.Option>;
+                })}
+              </Select>
+              <Select
+                style={{ width: 140 }}
+                placeholder="审核状态"
+                value={searchValues["status"]
+                  ? searchValues["status"]
+                  : undefined}
+                onChange={(e) => {
+                  searchValues["status"] = e;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              >
+                <Option value="0">未提交</Option>
+                <Option value="1">审核中</Option>
+                <Option value="2">完成</Option>
+                <Option value="3">驳回</Option>
+                <Option value="4">撤销</Option>
+              </Select>
+              <Input
+                placeholder="报销编号"
+                value={searchValues["checkNo"]
+                  ? searchValues["checkNo"]
+                  : ""}
+                onChange={(e) => {
+                  searchValues["checkNo"] = e.target.value;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              />
+              <div style={{ marginTop: 10 }}>
+                <span>报销时间:</span>
+                <RangePicker
+                  style={{ width: 300 }}
+                  value={[
+                    searchValues.startTime ? moment(searchValues.startTime) : null,
+                    searchValues.endTime ? moment(searchValues.endTime) : null,
+                  ]}
+                  onChange={(data, dataString) => {
+                    this.setState({
+                      searchValues: Object.assign(searchValues, {
+                        startTime: dataString[0],
+                        endTime: dataString[1],
+                      }),
+                    });
+                  }}
+                />
+                <Button
+                  type="primary"
+                  onClick={this.search}
+                  style={{ margin: "0 10px" }}
+                >
+                  搜索
+                </Button>
+                <Button onClick={this.reset}>重置</Button>
+              </div>
+            </div>
+          </TabPane>
+          <TabPane tab="更改表格显示数据" key="1">
+            <div style={{ marginLeft: 10 }}>
+              <ChooseList
+                columns={this.state.columns}
+                changeFn={this.changeList}
+                changeList={this.state.changeList}
+                top={55}
+                margin={11}
+              />
+            </div>
+          </TabPane>
+        </Tabs>
+        <div className="patent-table">
+          <Spin spinning={this.state.loading}>
+            <Table
+              bordered
+              columns={
+                this.state.changeList == undefined
+                  ? this.state.columns
+                  : this.state.changeList
+              }
+              dataSource={this.state.dataSource}
+              pagination={this.state.pagination}
+              // onRowDoubleClick={this.tableRowClick.bind(this)}
+              size="small"
+            />
+          </Spin>
+          <p
+            style={{ display: "inline-block", fontSize: "14px", color: "red" }}
+          >
+            {
+              <span style={{ marginRight: 10 }}>
+                {`金额总计(元):${this.state.totalAmount}`}
+              </span>
+            }
+          </p>
+        </div>
+        {
+          //审核弹窗
+          this.state.visible != "" &&
+          <Modal
+            width="400px"
+            maskClosable={false}
+            title="审核"
+            confirmLoading={this.state.loading}
+            visible={this.state.visible != ""}
+            onOk={() => { this.toExamine(visible == "adopt" ? 1 : visible == "reject" && 3) }}
+            okText={this.state.visible == "adopt" ? "通过" : this.state.visible == "reject" && "驳回"}
+            onCancel={() => {
+              this.setState({
+                visible: '',
+                reason: "",
+                checkData: {},
+              })
+            }}
+          >
+            <div style={{ width: "90%", margin: "0 auto" }}>
+              <TextArea
+                rows={4}
+                value={this.state.reason}
+                onChange={(e) => {
+                  this.setState({
+                    reason: e.target.value,
+                  })
+                }}
+                placeholder="请填写审核内容"
+              />
+            </div>
+          </Modal>
+        }
+        {
+          this.state.showDetails &&
+          <AccountDetails
+            showDetails={this.state.showDetails}
+            id={this.state.id}
+            isOperate={this.props.isOperate}
+            onCancel={() => { this.setState({ showDetails: false }) }}
+          />
+        }
+        {
+          // 审核日志
+          this.state.logvisible &&
+          <Modal
+            visible={this.state.logvisible}
+            className="admin-desc-content"
+            width="800px"
+            maskClosable={false}
+            title="审核日志"
+            footer={null}
+            onCancel={() => {
+              this.setState({
+                logvisible: false,
+              })
+            }}
+          >
+            <div className="patent-table">
+              <Spin spinning={this.state.loading}>
+                <Table
+                  columns={this.state.logcolumns}
+                  dataSource={this.state.logdataSour}
+                  pagination={false}
+                  bordered
+                  size="small"
+                />
+              </Spin>
+            </div>
+          </Modal>
+        }
+
+      </div>
+    );
+  },
+});
+
+export default AccountDetaillist;

File diff suppressed because it is too large
+ 529 - 422
js/component/manageCenter/financialManage/account/accountDetails.jsx


+ 26 - 3
js/component/manageCenter/financialManage/account/accountReview.jsx

@@ -72,6 +72,16 @@ const AccountReview = React.createClass({
           key: "totalAmount",
         },
         {
+          title: "实报金额(元)",
+          dataIndex: "realAmount",
+          key: "realAmount",
+        },
+        {
+          title: "报销编号",
+          dataIndex: "checkNo",
+          key: "checkNo",
+        },
+        {
           title: "报销至订单",
           dataIndex: "buyerName",
           key: "buyerName",
@@ -88,8 +98,8 @@ const AccountReview = React.createClass({
         },
         {
           title: "报销至部门",
-          dataIndex: "appDepName",
-          key: "appDepName",
+          dataIndex: "applyDepName",
+          key: "applyDepName",
           render: (text, record) => {
             return (
               <span>{record.targetType == 0 && text}</span>
@@ -126,7 +136,7 @@ const AccountReview = React.createClass({
           render: (text, record) => {
             return (
               <div>
-                <div>{record.appDepName || ""}</div>
+                <div>{record.applyDepName || ""}</div>
                 <div>{text || ""}</div>
               </div>
             );
@@ -241,6 +251,7 @@ const AccountReview = React.createClass({
     let datas = Object.assign(searchValues, {
       pageNo: pageNo || 1,
       pageSize: pagination.pageSize,
+      expenseMain: 1,
       processStatus: this.props.isOperate ? 1 : 2,
     });
     $.ajax({
@@ -648,6 +659,18 @@ const AccountReview = React.createClass({
                 <Option value="0">待审核</Option>
                 <Option value="1">已审核</Option>
               </Select>
+              <Input
+                placeholder="报销编号"
+                value={searchValues["checkNo"]
+                  ? searchValues["checkNo"]
+                  : ""}
+                onChange={(e) => {
+                  searchValues["checkNo"] = e.target.value;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              />
               <div style={{ marginTop: 10 }}>
                 <span>报销时间:</span>
                 <RangePicker

+ 17 - 2
js/component/manageCenter/financialManage/account/accountReview.less

@@ -35,6 +35,10 @@
   align-items: center;
   font-size: 12px;
 
+  td {
+    text-align: center;
+  }
+
   .ant-table-middle .ant-table-thead>tr>th:not(.ant-table-selection-column),
   .ant-table-middle .ant-table-tbody>tr>td {
     padding: 5px;
@@ -71,19 +75,30 @@
     font-size: 24px;
     font-weight: bold;
     padding: 2px 5px;
-    border-bottom: 1px solid #000;
+    // border-bottom: 1px solid #000;
     margin-bottom: 30px;
   }
 
+  .ant-table-wrapper {
+    width: 100%;
+  }
+
   .m_head {
     width: 100%;
     display: flex;
     flex-direction: row;
-    justify-content: space-between;
+    flex-wrap: wrap;
     font-size: 12px;
+
+    div {
+      width: 33%;
+      margin-bottom: 8px;
+
+    }
   }
 
   .ant-table-thead>tr>th {
     background: transparent;
+    text-align: center;
   }
 }

+ 816 - 0
js/component/manageCenter/financialManage/account/accountlist.jsx

@@ -0,0 +1,816 @@
+import React from "react";
+import $ from "jquery/src/ajax";
+import moment from "moment";
+import {
+  Button,
+  Form,
+  Input,
+  Spin,
+  Table,
+  Select,
+  message,
+  Tabs,
+  AutoComplete,
+  DatePicker,
+  Modal,
+} from "antd";
+import { ChooseList } from "../../order/orderNew/chooseList";
+import { ShowModal, getVehicleName, getTypeName, commonAdd, dealBigMoney } from "../../../tools"
+import ShowModalDiv from "@/showModal.jsx";
+import AccountDetails from "./accountDetails";
+import { accountType, accountStatus } from "@/dataDic";
+
+const FormItem = Form.Item;
+const { RangePicker } = DatePicker;
+const { TabPane } = Tabs;
+
+const AccountList = React.createClass({
+
+  getInitialState() {
+    return {
+      showDetails: false,
+      data: {},
+      logvisible: false,
+      logdataSour: [],
+      visible: "",
+      reason: "",
+      checkData: {},
+      aname: "",
+      searchValues: {}, // 列表筛选条件
+      loading: false, //加载动画
+      changeList: undefined, // 更改后的表格显示数据
+      dataSource: [], // 列表数据
+      departmentArr: [],
+      pagination: {
+        defaultCurrent: 1,
+        defaultPageSize: 10,
+        showQuickJumper: true,
+        pageSize: 10,
+        onChange: function (page) {
+          this.loadData(page);
+        }.bind(this),
+        showTotal: function (total) {
+          return "共" + total + "条数据";
+        },
+      },
+      columns: [
+        {
+          title: "类型",
+          dataIndex: "type",
+          key: "type",
+          render: (text, record) => {
+            return (
+              <span>
+                {text == 0 ? record.typeOther : accountType.find(item => item.value === text).label}
+              </span>
+            );
+          },
+        },
+        {
+          title: "报销金额(元)",
+          dataIndex: "totalAmount",
+          key: "totalAmount",
+        },
+        {
+          title: "实报金额(元)",
+          dataIndex: "realAmount",
+          key: "realAmount",
+        },
+        {
+          title: "报销编号",
+          dataIndex: "checkNo",
+          key: "checkNo",
+        },
+        {
+          title: "报销至订单",
+          dataIndex: "buyerName",
+          key: "buyerName",
+          render: (text, record) => {
+            return (
+              record.targetType == 0
+                ? <div>固定费用</div>
+                : <div>
+                  <div>{text || ""}</div>
+                  <div>{record.contractNo || ""}</div>
+                </div>
+            );
+          },
+        },
+        {
+          title: "报销至部门",
+          dataIndex: "applyDepName",
+          key: "applyDepName",
+          render: (text, record) => {
+            return (
+              <span>{record.targetType == 0 && text}</span>
+            );
+          },
+        },
+        {
+          title: "报销人",
+          dataIndex: "aname",
+          key: "aname",
+        },
+
+        {
+          title: "财务负责人",
+          dataIndex: "financeName",
+          key: "financeName",
+        },
+        {
+          title: "状态",
+          dataIndex: "status",
+          key: "status",
+          render: (text, record) => {
+            return (
+              <span style={{ color: accountStatus[text].color }}>
+                {accountStatus[text].label}
+              </span>
+            );
+          },
+        },
+        {
+          title: "报销公司/支付公司",
+          dataIndex: "payDepName",
+          key: "payDepName",
+          render: (text, record) => {
+            return (
+              <div>
+                <div>{record.applyDepName || ""}</div>
+                <div>{text || ""}</div>
+              </div>
+            );
+          },
+        },
+        {
+          title: "报销时间",
+          dataIndex: "createTimeStr",
+          key: "createTimeStr",
+        },
+        {
+          title: "操作",
+          dataIndex: "operate",
+          key: "operate",
+          render: (text, record) => {
+            return (
+              <div>
+                <div>
+                  {this.props.isOperate &&
+                    <Button type="primary"
+                      style={{ margin: 4 }}
+                      onClick={() => { this.download(record.attachmentUrl) }}
+                    >下载</Button>}
+                  {this.props.isOperate && record.examine == 1 &&
+                    <Button type="primary"
+                      style={{ margin: 4 }}
+                      onClick={(e) => {
+                        e.stopPropagation();
+                        this.setState({
+                          visible: "adopt",
+                          checkData: record,
+                        })
+                      }}
+                    >同意</Button>}
+                  {this.props.isOperate && record.examine == 1 &&
+                    <Button type="danger"
+                      style={{ margin: 4 }}
+                      onClick={(e) => {
+                        e.stopPropagation();
+                        this.setState({
+                          visible: "reject",
+                          checkData: record,
+                        })
+                      }}
+                    >驳回</Button>}
+                  {record.status != 0 && <Button
+                    style={{ margin: 4 }}
+                    onClick={() => {
+                      this.setState({
+                        logvisible: true
+                      })
+                      this.getLogData(record.mainId)
+                    }}>日志</Button>}
+                </div>
+              </div>
+            )
+          }
+        },
+      ],
+      logcolumns: [
+        {
+          title: "审核人",
+          dataIndex: "auditorName",
+          key: "auditorName"
+        },
+        {
+          title: "操作",
+          dataIndex: "status",
+          key: "status",
+          width: 120,
+          render: (text, record) => {
+            return (
+              <span style={{ color: ["#1D4FEA", "#34DE38", "#108EE9", "red", "#1D4FEA"][text] }}>
+                {["【发起】", "【通过】", "【完成】", "【驳回】", "【重新发起】"][text]}
+                {this.state.processStatus == record.processStatus && !record.id &&
+                  <span style={{ color: "#FFA500" }}>&nbsp;审核中...</span>}
+              </span>
+            );
+          },
+        },
+        {
+          title: "操作时间",
+          dataIndex: "createTimeStr",
+          key: "createTimeStr",
+          width: 88,
+        },
+        {
+          title: "备注",
+          dataIndex: "remarks",
+          key: "remarks",
+          render: (text, record) => {
+            return (
+              <div style={{ minWidth: 250 }}>{text}</div>
+            )
+          }
+        }
+      ],
+    };
+  },
+
+  componentWillMount() {
+    this.departmentList();
+    this.loadData();
+  },
+
+  // 列表接口
+  loadData(pageNo) {
+    const { searchValues, pagination } = this.state;
+    this.setState({
+      loading: true,
+    });
+    let datas = Object.assign(searchValues, {
+      pageNo: pageNo || 1,
+      pageSize: pagination.pageSize,
+      expenseMain: 0,
+      processStatus: this.props.isOperate ? 1 : 2,
+    });
+    $.ajax({
+      method: "get",
+      dataType: "json",
+      crossDomain: false,
+      url: globalConfig.context + "/api/admin/expenseAccount/pageList",
+      data: datas,
+      success: function (data) {
+        ShowModal(this);
+        this.setState({
+          loading: false,
+        });
+        if (data.error && data.error.length === 0) {
+          if (data.data.list) {
+            pagination.current = data.data.pageNo;
+            pagination.total = data.data.totalCount;
+            if (data.data && data.data.list && !data.data.list.length) {
+              pagination.current = 0;
+              pagination.total = 0;
+            }
+            this.setState({
+              dataSource: data.data.list,
+              pagination: this.state.pagination,
+              pageNo: data.data.pageNo,
+              totalAmount: data.data.totalAmount,
+            });
+          } else {
+            this.setState({
+              dataSource: data.data,
+              pagination: false,
+            });
+          }
+        } else {
+          message.warning(data.error[0].message);
+        }
+      }.bind(this),
+    }).always(
+      function () {
+        this.setState({
+          loading: false,
+        });
+      }.bind(this)
+    );
+  },
+
+  // 日志
+  getLogData(eaid) {
+    $.ajax({
+      method: "get",
+      dataType: "json",
+      crossDomain: false,
+      url: globalConfig.context + "/api/admin/expenseAccount/log/list",
+      data: { eaid },
+      success: function (data) {
+        if (data.error.length === 0) {
+          this.setState({
+            logdataSour: data.data || []
+          });
+          this.isHere(data.data || [])
+        } else {
+          message.warning(data.error[0].message);
+        }
+      }.bind(this)
+    }).always(
+      function () {
+
+      }.bind(this)
+    );
+  },
+
+  // 
+  isHere(list = []) {
+    for (var i = 0; i < list.length; i++) {
+      if (!list[i].id) {
+        this.setState({
+          processStatus: list[i].processStatus
+        })
+        return
+      }
+    }
+  },
+
+  download(urls) {
+    if (!urls) {
+      message.error("暂无可下载的附件!");
+    } else {
+      let list = urls.split(',') || []
+      list.forEach(e => {
+        var aLink = document.createElement('a');
+        aLink.download = e;
+        aLink.href = globalConfig.context + `/open/download?fileName=${e}&delete=false`;
+        document.body.appendChild(aLink);
+        aLink.click();
+        document.body.removeChild(aLink);
+      });
+
+
+
+
+    }
+  },
+
+  departmentList() {
+    $.ajax({
+      method: "get",
+      dataType: "json",
+      crossDomain: false,
+      url: globalConfig.context + "/api/admin/organization/selectSuperId",
+      data: {},
+      success: function (data) {
+        let thedata = data.data;
+        let theArr = [];
+        if (!thedata) {
+          if (data.error && data.error.length) {
+            message.warning(data.error[0].message);
+          }
+        } else {
+          thedata.map(function (item, index) {
+            theArr.push({
+              key: index,
+              name: item.name,
+              id: item.id
+            });
+          });
+        }
+        this.setState({
+          departmentArr: theArr
+        });
+      }.bind(this)
+    }).always(
+      function () {
+
+      }.bind(this)
+    );
+  },
+
+  // 审核
+  toExamine(num) {
+    const { checkData, reason } = this.state
+    if (!reason) {
+      message.warning("请填写审核说明~");
+      return;
+    }
+    this.setState({
+      loading: true,
+    });
+    $.ajax({
+      method: "POST",
+      dataType: "json",
+      crossDomain: false,
+      url: globalConfig.context + "/api/admin/expenseAccount/examine",
+      data: {
+        id: checkData.id,
+        reason,
+        status: num,//1同意 3驳回
+      },
+    }).done(
+      function (data) {
+        if (!data.error.length) {
+          message.success("审核成功!");
+          this.setState({
+            visible: "",
+            reason: "",
+            showDetails: false,
+            checkData: {},
+          });
+          this.loadData()
+        } else {
+          message.warning(data.error[0].message);
+        }
+      }.bind(this)
+    );
+  },
+
+  tableRowClick(e) {
+    this.setState({
+      showDetails: true,
+      id: e.id,
+    })
+    // this.getDetails(e.id)
+
+  },
+
+  // 查询负责人
+  followUp(e) {
+    this.setState({
+      aname: e
+    });
+    $.ajax({
+      method: "get",
+      dataType: "json",
+      crossDomain: false,
+      url: globalConfig.context + "/api/admin/customer/listAdminByName",
+      data: {
+        adminName: e,
+      },
+      success: function (data) {
+        let thedata = data.data || [];
+        if (!thedata) {
+          if (data.error && data.error.length) {
+            message.warning(data.error[0].message);
+          }
+          thedata = {};
+        }
+        this.setState({
+          fjlist: thedata,
+        });
+      }.bind(this),
+    }).always(
+      function () {
+        this.setState({
+          loading: false,
+        });
+      }.bind(this)
+    );
+  },
+
+  // 选中负责人
+  selectF(value) {
+    const { searchValues, fjlist } = this.state;
+    const newdataSources = JSON.stringify(fjlist) == "{}" ? [] : fjlist;
+    this.setState({
+      searchValues: Object.assign(searchValues, {
+        aid: newdataSources.find((item) => item.name == value).id,
+      }),
+    });
+  },
+
+  // 搜索
+  search() {
+    this.loadData();
+  },
+
+  // 重置
+  reset() {
+    this.setState({
+      aname: "",
+      searchValues: JSON.parse(JSON.stringify({})),
+    }, () => {
+      this.loadData();
+    })
+  },
+
+  changeList(arr) {
+    const newArr = [];
+    this.state.columns.forEach((item) => {
+      arr.forEach((val) => {
+        if (val === item.title) {
+          newArr.push(item);
+        }
+      });
+    });
+    this.setState({
+      changeList: newArr,
+    });
+  },
+
+
+  render() {
+    const { TextArea } = Input
+    const { searchValues, visible, } = this.state
+    const formItemLayout = {
+      labelCol: { span: 5 },
+      wrapperCol: { span: 18 },
+    };
+    const dataSources = this.state.fjlist || [];
+    const options = dataSources.map((group) => (
+      <Select.Option key={group.id} value={group.name}>
+        {group.name}
+      </Select.Option>
+    ));
+
+    return (
+      <div className="user-content">
+        <ShowModalDiv ShowModal={this.state.showModal} />
+        <div className="content-title" style={{ marginBottom: 10 }}>
+          <span style={{ fontWeight: 900, fontSize: 16 }}>费用单列表</span>
+        </div>
+        <Tabs defaultActiveKey="2" className="test">
+          <TabPane tab="搜索" key="2">
+            <div className="user-search" style={{ marginLeft: 10 }}>
+              <Input
+                placeholder="合同编号"
+                value={searchValues["contractNo"]
+                  ? searchValues["contractNo"]
+                  : ""}
+                onChange={(e) => {
+                  searchValues["contractNo"] = e.target.value;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              />
+              <Input
+                placeholder="客户名称"
+                value={searchValues["username"]
+                  ? searchValues["username"]
+                  : ""}
+                onChange={(e) => {
+                  searchValues["username"] = e.target.value;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              />
+              <Select
+                style={{ width: 140 }}
+                placeholder="报销类型"
+                value={searchValues["type"]
+                  ? searchValues["type"]
+                  : undefined}
+                onChange={(e) => {
+                  searchValues["type"] = e;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              >
+                <Option value="1">差旅费</Option>
+                <Option value="2">非业务报销</Option>
+                <Option value="3">第三方付款</Option>
+                <Option value="4">申请借支</Option>
+                <Option value="5">申请抵扣</Option>
+                <Option value="0">其他</Option>
+              </Select>
+              <AutoComplete
+                className="certain-category-search"
+                dropdownClassName="certain-category-search-dropdown"
+                dropdownMatchSelectWidth={false}
+                style={{ width: 140 }}
+                dataSource={options}
+                placeholder="报销人"
+                value={this.state.aname}
+                onChange={this.followUp.bind(this)}
+                filterOption={true}
+                onSelect={this.selectF.bind(this)}
+              >
+                <Input />
+              </AutoComplete>
+              <Select
+                placeholder="所属部门"
+                style={{ width: 200, marginRight: 10 }}
+                value={searchValues["depId"]
+                  ? searchValues["depId"]
+                  : undefined}
+                onChange={e => {
+                  searchValues["depId"] = e;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              >
+                {this.state.departmentArr.map(function (item) {
+                  return <Select.Option key={item.id}>{item.name}</Select.Option>;
+                })}
+              </Select>
+              <Select
+                placeholder="申请部门"
+                style={{ width: 200, marginRight: 10 }}
+                value={searchValues["applyDep"]
+                  ? searchValues["applyDep"]
+                  : undefined}
+                onChange={e => {
+                  searchValues["applyDep"] = e;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              >
+                {this.state.departmentArr.map(function (item) {
+                  return <Select.Option key={item.id}>{item.name}</Select.Option>;
+                })}
+              </Select>
+              <Select
+                placeholder="支付部门"
+                style={{ width: 200, marginRight: 10 }}
+                value={searchValues["payDep"]
+                  ? searchValues["payDep"]
+                  : undefined}
+                onChange={e => {
+                  searchValues["payDep"] = e;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              >
+                {this.state.departmentArr.map(function (item) {
+                  return <Select.Option key={item.id}>{item.name}</Select.Option>;
+                })}
+              </Select>
+              <Select
+                style={{ width: 140 }}
+                placeholder="审核状态"
+                value={searchValues["examineStatus"]
+                  ? searchValues["examineStatus"]
+                  : undefined}
+                onChange={(e) => {
+                  searchValues["examineStatus"] = e;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              >
+                <Option value="0">待审核</Option>
+                <Option value="1">已审核</Option>
+              </Select>
+              <Input
+                placeholder="报销编号"
+                value={searchValues["checkNo"]
+                  ? searchValues["checkNo"]
+                  : ""}
+                onChange={(e) => {
+                  searchValues["checkNo"] = e.target.value;
+                  this.setState({
+                    searchValues: searchValues,
+                  });
+                }}
+              />
+              <div style={{ marginTop: 10 }}>
+                <span>报销时间:</span>
+                <RangePicker
+                  style={{ width: 300 }}
+                  value={[
+                    searchValues.startTime ? moment(searchValues.startTime) : null,
+                    searchValues.endTime ? moment(searchValues.endTime) : null,
+                  ]}
+                  onChange={(data, dataString) => {
+                    this.setState({
+                      searchValues: Object.assign(searchValues, {
+                        startTime: dataString[0],
+                        endTime: dataString[1],
+                      }),
+                    });
+                  }}
+                />
+                <Button
+                  type="primary"
+                  onClick={this.search}
+                  style={{ margin: "0 10px" }}
+                >
+                  搜索
+                </Button>
+                <Button onClick={this.reset}>重置</Button>
+              </div>
+            </div>
+          </TabPane>
+          <TabPane tab="更改表格显示数据" key="1">
+            <div style={{ marginLeft: 10 }}>
+              <ChooseList
+                columns={this.state.columns}
+                changeFn={this.changeList}
+                changeList={this.state.changeList}
+                top={55}
+                margin={11}
+              />
+            </div>
+          </TabPane>
+        </Tabs>
+        <div className="patent-table">
+          <Spin spinning={this.state.loading}>
+            <Table
+              bordered
+              columns={
+                this.state.changeList == undefined
+                  ? this.state.columns
+                  : this.state.changeList
+              }
+              dataSource={this.state.dataSource}
+              pagination={this.state.pagination}
+              // onRowDoubleClick={this.tableRowClick.bind(this)}
+              size="small"
+            />
+          </Spin>
+          <p
+            style={{ display: "inline-block", fontSize: "14px", color: "red" }}
+          >
+            {
+              <span style={{ marginRight: 10 }}>
+                {`金额总计(元):${this.state.totalAmount}`}
+              </span>
+            }
+          </p>
+        </div>
+        {
+          //审核弹窗
+          this.state.visible != "" &&
+          <Modal
+            width="400px"
+            maskClosable={false}
+            title="审核"
+            confirmLoading={this.state.loading}
+            visible={this.state.visible != ""}
+            onOk={() => { this.toExamine(visible == "adopt" ? 1 : visible == "reject" && 3) }}
+            okText={this.state.visible == "adopt" ? "通过" : this.state.visible == "reject" && "驳回"}
+            onCancel={() => {
+              this.setState({
+                visible: '',
+                reason: "",
+                checkData: {},
+              })
+            }}
+          >
+            <div style={{ width: "90%", margin: "0 auto" }}>
+              <TextArea
+                rows={4}
+                value={this.state.reason}
+                onChange={(e) => {
+                  this.setState({
+                    reason: e.target.value,
+                  })
+                }}
+                placeholder="请填写审核内容"
+              />
+            </div>
+          </Modal>
+        }
+        {
+          this.state.showDetails &&
+          <AccountDetails
+            showDetails={this.state.showDetails}
+            id={this.state.id}
+            isOperate={this.props.isOperate}
+            onCancel={() => { this.setState({ showDetails: false }) }}
+          />
+        }
+        {
+          // 审核日志
+          this.state.logvisible &&
+          <Modal
+            visible={this.state.logvisible}
+            className="admin-desc-content"
+            width="800px"
+            maskClosable={false}
+            title="审核日志"
+            footer={null}
+            onCancel={() => {
+              this.setState({
+                logvisible: false,
+              })
+            }}
+          >
+            <div className="patent-table">
+              <Spin spinning={this.state.loading}>
+                <Table
+                  columns={this.state.logcolumns}
+                  dataSource={this.state.logdataSour}
+                  pagination={false}
+                  bordered
+                  size="small"
+                />
+              </Spin>
+            </div>
+          </Modal>
+        }
+
+      </div>
+    );
+  },
+});
+
+export default AccountList;

+ 18 - 1
js/component/manageCenter/financialManage/content.jsx

@@ -325,7 +325,24 @@ class Content extends Component {
           });
         });
         break;
-
+      // 费用单列表
+      case "accountlist":
+        require.ensure([], () => {
+          const AccountList = require("./account/accountlist").default;
+          this.setState({
+            component: <AccountList />,
+          });
+        });
+        break;
+      // 费用明细表
+      case "accountDetaillist":
+        require.ensure([], () => {
+          const AccountDetailList = require("./account/accountDetaillist").default;
+          this.setState({
+            component: <AccountDetailList />,
+          });
+        });
+        break;
       default:
         require.ensure([], () => {
           let Module = require("../module").default;

+ 12 - 0
js/component/tools.js

@@ -2318,6 +2318,18 @@ const obj = {
     return theType;
   },
 
+  getSecondaryAccountName(type, other = "其他"){
+    let theType = "";
+    typeLists.map(function (item) {
+      if (item.value == type) {
+        theType = item.label;
+        if (item.value == 0) {
+          theType = other
+        }
+      }
+    });
+    return theType;
+  },
   // 获取交通工具类型
   getVehicleName(type, other = "其他") {
     let theType = "";

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "afanti",
-  "version": "1.2.98",
+  "version": "1.2.99",
   "description": "",
   "main": "index.js",
   "scripts": {