From 89ee68c59cdcaa4b7fa0178be42d58bec651ee73 Mon Sep 17 00:00:00 2001
From: king <18310653075@163.com>
Date: 星期四, 09 七月 2020 12:15:03 +0800
Subject: [PATCH] 2020-07-09

---
 src/assets/img/weixinpay.jpg                           |    0 
 package-lock.json                                      |   15 ++
 src/views/pay/index.scss                               |   93 ++++++++++++-
 src/mob/controller/index.jsx                           |   68 ++++++++-
 src/tabviews/zshare/normalTable/index.jsx              |   20 ++
 src/assets/img/weixinscan.png                          |    0 
 src/mob/controller/index.scss                          |   23 +++
 src/tabviews/zshare/actionList/excelInbutton/index.jsx |    6 
 src/setupProxy.js                                      |   16 +-
 src/views/pay/index.jsx                                |  154 ++++++++++++++++++++-
 src/api/index.js                                       |   10 +
 src/tabviews/zshare/actionList/newpagebutton/index.jsx |    5 
 package.json                                           |    1 
 src/mob/login/index.scss                               |    8 +
 14 files changed, 379 insertions(+), 40 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 0d30f38..48ebc57 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13265,6 +13265,21 @@
       "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
       "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc="
     },
+    "qr.js": {
+      "version": "0.0.0",
+      "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz",
+      "integrity": "sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8="
+    },
+    "qrcode.react": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-1.0.0.tgz",
+      "integrity": "sha512-jBXleohRTwvGBe1ngV+62QvEZ/9IZqQivdwzo9pJM4LQMoCM2VnvNBnKdjvGnKyDZ/l0nCDgsPod19RzlPvm/Q==",
+      "requires": {
+        "loose-envify": "1.4.0",
+        "prop-types": "15.7.2",
+        "qr.js": "0.0.0"
+      }
+    },
     "qs": {
       "version": "6.5.2",
       "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
diff --git a/package.json b/package.json
index 7905f1b..406bec5 100644
--- a/package.json
+++ b/package.json
@@ -60,6 +60,7 @@
     "postcss-preset-env": "6.7.0",
     "postcss-safe-parser": "4.0.1",
     "prop-types": "^15.7.2",
+    "qrcode.react": "^1.0.0",
     "rc-form": "^2.4.11",
     "react": "^16.9.0",
     "react-app-polyfill": "^1.0.2",
diff --git a/src/api/index.js b/src/api/index.js
index 56fdc9c..d2082ee 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -448,6 +448,16 @@
   }
 
   /**
+   * @description 鑾峰彇寰俊鏀粯浜岀淮鐮�
+   */
+  getWxNativePay (param) {
+    return axios({
+      url: '/wxpay/wxNativePay',
+      data: param
+    })
+  }
+
+  /**
    * @description 鏂囦欢涓婁紶
    */
   getFileUpload (param) {
diff --git a/src/assets/img/weixinpay.jpg b/src/assets/img/weixinpay.jpg
new file mode 100644
index 0000000..3ac2692
--- /dev/null
+++ b/src/assets/img/weixinpay.jpg
Binary files differ
diff --git a/src/assets/img/weixinscan.png b/src/assets/img/weixinscan.png
new file mode 100644
index 0000000..4ca9e8c
--- /dev/null
+++ b/src/assets/img/weixinscan.png
Binary files differ
diff --git a/src/mob/controller/index.jsx b/src/mob/controller/index.jsx
index 6e9ebc0..c6f5e17 100644
--- a/src/mob/controller/index.jsx
+++ b/src/mob/controller/index.jsx
@@ -6,6 +6,7 @@
 import zhCN from '@/locales/zh-CN/mob.js'
 import enUS from '@/locales/en-US/mob.js'
 import ColorSketch from '@/mob/colorsketch'
+import FileUpload from '@/tabviews/zshare/fileupload'
 import './index.scss'
 
 const { Panel } = Collapse
@@ -21,7 +22,8 @@
     dict: localStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
     card: null,
     fontColor: '#000000',
-    backgroundColor: '#ffffff'
+    backgroundColor: '#ffffff',
+    bgimages: []
   }
 
   UNSAFE_componentWillReceiveProps (nextProps) {
@@ -31,11 +33,21 @@
       }, () => {
         if (!nextProps.editElem) return
         let _card = fromJS(nextProps.editElem).toJS()
+        let bgImg = _card.backgroundImage || ''
+
+        if (bgImg && /^linear-gradient/.test(bgImg)) {
+          bgImg = bgImg.replace('linear-gradient(', '')
+          bgImg = bgImg.replace(')', '')
+        } else if (bgImg && /^url/.test(bgImg)) {
+          bgImg = bgImg.replace('url(', '')
+          bgImg = bgImg.replace(')', '')
+        }
 
         this.setState({
           card: _card,
           fontColor: _card.color || '#000000',
-          backgroundColor: _card.backgroundColor || '#ffffff'
+          backgroundColor: _card.backgroundColor || '#ffffff',
+          backgroundImage: bgImg,
         })
       })
     }
@@ -159,8 +171,42 @@
     })
   }
 
+  imgChange = (list) => {
+    const { card } = this.state
+
+    if (list[0] && list[0].response) {
+      this.setState({
+        bgimages: [],
+        backgroundImage: list[0].response
+      })
+      this.props.updateStyle({componentId: card.componentId, uuid: card.uuid, style: {backgroundImage: `url(${list[0].response})`}})
+    } else {
+      this.setState({bgimages: list})
+    }
+  }
+
+  changeBackgroundImageInput = (e) => {
+    this.setState({
+      backgroundImage: e.target.value
+    })
+  }
+
+  submitBackgroundImage = (e) => {
+    const { card } = this.state
+    let val = e.target.value
+    val = val.replace(/^\s*|\s*$/ig, '')
+
+    if (/^http|^\/\//.test(val)) {
+      val = `url(${val})`
+    } else if (/^#|,/ig.test(val)) {
+      val = `linear-gradient(${val})`
+    }
+
+    this.props.updateStyle({componentId: card.componentId, uuid: card.uuid, style: {backgroundImage: val}})
+  }
+
   render () {
-    const { card, fontColor, backgroundColor } = this.state
+    const { card, fontColor, backgroundColor, backgroundImage, bgimages } = this.state
     const formItemLayout = {
       labelCol: {
         xs: { span: 24 },
@@ -262,7 +308,7 @@
                 </Form.Item>
               </Col>
             </Panel> : null}
-            {card.items.includes('background') ? <Panel header="鑳屾櫙" key="1">
+            {card.items.includes('background') ? <Panel header="鑳屾櫙" key="background">
               <Col span={24}>
                 <Form.Item
                   colon={false}
@@ -279,14 +325,18 @@
                   label={<Icon title="鑳屾櫙鍥剧墖" type="picture" />}
                   labelCol={{xs: { span: 24 }, sm: { span: 4 }}} wrapperCol={ {xs: { span: 24 }, sm: { span: 20 }} }
                 >
-                  <ColorSketch color={card.backgroundColor || '#ffffff'} changeColor={this.changeBackgroundColor} />
-                  <Input value={backgroundColor} onChange={this.changeBackgroundColorInput} />
+                  <FileUpload value={bgimages} maxFile={2} fileType="text" onChange={this.imgChange}/>
+                  <Input placeholder="" value={backgroundImage} autoComplete="off" onBlur={this.submitBackgroundImage} onPressEnter={this.submitBackgroundImage} onChange={this.changeBackgroundImageInput} />
                 </Form.Item>
               </Col>
             </Panel> : null}
-            <Panel header="杈硅窛" key="2">
-              杈硅窛
-            </Panel>
+            {card.items.includes('border') ? <Panel header="杈规" key="border">
+              <Col span={12}>
+                <Form.Item colon={false} label={<Icon title="瀛椾綋澶у皬" type="font-size" />}>
+                  <InputNumber defaultValue={card.fontSize || 14} min={12} max={100} precision={0} onChange={this.changeFontSize} />
+                </Form.Item>
+              </Col>
+            </Panel> : null}
             <Panel header="鍏朵粬" key="3">
               鍏朵粬
             </Panel>
diff --git a/src/mob/controller/index.scss b/src/mob/controller/index.scss
index 7a70d78..6b87772 100644
--- a/src/mob/controller/index.scss
+++ b/src/mob/controller/index.scss
@@ -85,6 +85,29 @@
                   }
                 }
               }
+              .fileupload-form-container {
+                .ant-btn {
+                  height: 28px;
+                }
+                .ant-upload-list-item {
+                  .ant-upload-list-item-info {
+                    background: transparent;
+                    color: rgba(255, 255, 255, 0.85);
+                    i {
+                      color: rgba(255, 255, 255, 0.85);
+                    }
+                  }
+                  .anticon-close {
+                    color: rgba(255, 255, 255, 0.85);
+                  }
+                  .anticon-close:hover {
+                    color: rgba(255, 255, 255, 0.85);
+                  }
+                }
+                .ant-upload-list-item:hover .ant-upload-list-item-info {
+                  background: transparent;
+                }
+              }
             }
           }
         }
diff --git a/src/mob/login/index.scss b/src/mob/login/index.scss
index 24ae6af..89b6cdd 100644
--- a/src/mob/login/index.scss
+++ b/src/mob/login/index.scss
@@ -4,6 +4,10 @@
   height: 100%;
   overflow: hidden;
   // background-image: linear-gradient(#378DBE, #46C29E, #48A9D6);
+  background-repeat: no-repeat;
+  background-size: cover;
+  background-position: center center;
+
 
   .logo {
     position: relative;
@@ -151,6 +155,10 @@
     border: 1px dotted transparent;
     overflow: visible;
     letter-spacing: 0px;
+    background-repeat: no-repeat;
+    background-size: cover;
+    background-position: center center;
+    
     span {
       font-style: inherit;
       font-weight: inherit;
diff --git a/src/setupProxy.js b/src/setupProxy.js
index a14f43b..1aca9db 100644
--- a/src/setupProxy.js
+++ b/src/setupProxy.js
@@ -33,12 +33,12 @@
     }
   }))
 
-  // app.use(proxy('/local', { 
-  //   target: 'http://127.0.0.1:8888',
-  //   secure: false,
-  //   changeOrigin: true,
-  //   pathRewrite: {
-  //   '^/local': '/'
-  //   }
-  // }))
+  app.use(proxy('/wxpay', {
+    target: `${host}/${service}wxpay`,
+    secure: false,
+    changeOrigin: true,
+    pathRewrite: {
+    '^/wxpay': '/'
+    }
+  }))
 }
\ No newline at end of file
diff --git a/src/tabviews/zshare/actionList/excelInbutton/index.jsx b/src/tabviews/zshare/actionList/excelInbutton/index.jsx
index 49edf75..6130d75 100644
--- a/src/tabviews/zshare/actionList/excelInbutton/index.jsx
+++ b/src/tabviews/zshare/actionList/excelInbutton/index.jsx
@@ -225,6 +225,12 @@
       })
       this.updateStatus('over')
       return
+    } else if (data.length * btn.verify.columns.length > 30000) {
+      notification.warning({
+        top: 92,
+        message: '褰撳墠瀵煎叆鏁版嵁閲忚繃澶э紝濡傞亣閿欒鎻愮ず锛岃鍒嗘壒瀵煎叆锛�',
+        duration: 5
+      })
     }
 
     let result = Utils.getExcelInSql(btn, data, this.state.dict)
diff --git a/src/tabviews/zshare/actionList/newpagebutton/index.jsx b/src/tabviews/zshare/actionList/newpagebutton/index.jsx
index 7901770..a323132 100644
--- a/src/tabviews/zshare/actionList/newpagebutton/index.jsx
+++ b/src/tabviews/zshare/actionList/newpagebutton/index.jsx
@@ -82,13 +82,14 @@
       let src = '#/print/' + window.btoa('ID=' + Id + msg + cloudmsg)
       window.open(src)
     } else if (btn.pageTemplate === 'pay') {
-      let url = '#/pay/' +  window.btoa(`ID=${Id}&LoginUID=${sessionStorage.getItem('LoginUID')}`)
+      let _p = `ID=${Id}&userid=${sessionStorage.getItem('UserID')}&LoginUID=${sessionStorage.getItem('LoginUID')}&logo=${window.GLOB.mainlogo}&name=${sessionStorage.getItem('Full_Name')}&suid=${sessionStorage.getItem('SessionUid')}&icp=${window.GLOB.ICP}&copyRight=${window.GLOB.copyRight}`
+      let url = '#/pay/' +  window.btoa(window.encodeURIComponent(_p))
 
       window.open(url)
     } else if (btn.pageTemplate === 'custom') {
       let url = btn.url
       if (btn.Ot === 'requiredSgl' && btn.joint !== 'false') {
-        url = url + `?ID=${Id}&appkey=${window.GLOB.appkey}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
+        url = url + `?id=${Id}&appkey=${window.GLOB.appkey}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
       } else if (btn.joint !== 'false') {
         url = url + `?appkey=${window.GLOB.appkey}&LoginUID=${sessionStorage.getItem('LoginUID') || ''}`
       }
diff --git a/src/tabviews/zshare/normalTable/index.jsx b/src/tabviews/zshare/normalTable/index.jsx
index 337f4fd..658c359 100644
--- a/src/tabviews/zshare/normalTable/index.jsx
+++ b/src/tabviews/zshare/normalTable/index.jsx
@@ -458,7 +458,15 @@
       }
 
       if (item.joint === 'true' && _href) {
-        let _param = window.btoa('id=' + record[this.props.setting.primaryKey] + '&userid=' + sessionStorage.getItem('UserID') + '&loginuid=' + sessionStorage.getItem('LoginUID'))
+        let _quary = `id=${record[this.props.setting.primaryKey]}&userid=${sessionStorage.getItem('UserID')}&appkey=${window.GLOB.appkey}&LoginUID=${sessionStorage.getItem('LoginUID')}`
+        let _param = ''
+        
+        try {
+          _param = window.btoa(_quary)
+        } catch {
+          _param = window.btoa(window.encodeURIComponent(_quary))
+        }
+        
         _href += '?' + _param
       }
 
@@ -587,7 +595,15 @@
           }
 
           if (col.joint === 'true' && _href) {
-            let _param = window.btoa('id=' + record[this.props.setting.primaryKey] + '&userid=' + sessionStorage.getItem('UserID') + '&loginuid=' + sessionStorage.getItem('LoginUID'))
+            let _quary = `id=${record[this.props.setting.primaryKey]}&userid=${sessionStorage.getItem('UserID')}&appkey=${window.GLOB.appkey}&LoginUID=${sessionStorage.getItem('LoginUID')}`
+            let _param = ''
+
+            try {
+              _param = window.btoa(_quary)
+            } catch {
+              _param = window.btoa(window.encodeURIComponent(_quary))
+            }
+
             _href += '?' + _param
           }
 
diff --git a/src/views/pay/index.jsx b/src/views/pay/index.jsx
index 50b306f..44c1372 100644
--- a/src/views/pay/index.jsx
+++ b/src/views/pay/index.jsx
@@ -1,17 +1,32 @@
 import React, {Component} from 'react'
+import moment from 'moment'
+import md5 from 'md5'
+import QRCode from 'qrcode.react'
+import { notification, Radio } from 'antd'
 
-// import Api from '@/api'
+import Api from '@/api'
+import Utils from '@/utils/utils.js'
+import WeiXinPay from '@/assets/img/weixinpay.jpg'
+import WeiXinScan from '@/assets/img/weixinscan.png'
 import './index.scss'
 
 class Pay extends Component {
   state = {
-    orderId: ''
+    orderId: '',
+    orderNo: '',
+    logo: '',
+    name: '',
+    copyRight: '',
+    icp: '',
+    total: '',
+    unit: '',
+    qrcode: ''
   }
 
   UNSAFE_componentWillMount () {
-    let _param = window.atob(this.props.match.params.param)
+    let _urlparam = window.decodeURIComponent(window.atob(this.props.match.params.param))
     let _params = {}
-    _param.split('&').forEach(cell => {
+    _urlparam.split('&').forEach(cell => {
       let _cell = cell.split('=')
       _params[_cell[0]] = _cell[1]
     })
@@ -19,22 +34,141 @@
     if (!sessionStorage.getItem('LoginUID') && _params.LoginUID) {
       sessionStorage.setItem('LoginUID', _params.LoginUID)
     }
+    if (!sessionStorage.getItem('UserID') && _params.userid) {
+      sessionStorage.setItem('UserID', _params.userid)
+    }
+    if (!sessionStorage.getItem('SessionUid') && _params.suid) {
+      sessionStorage.setItem('SessionUid', _params.suid)
+    }
 
     this.setState({
-      orderId: _params.ID
+      orderId: _params.ID,
+      logo: _params.logo,
+      name: _params.name,
+      copyRight: _params.copyRight,
+      icp: _params.icp
+    })
+
+    if (_params.ID) {
+      this.getOrder(_params.ID)
+    } else {
+      notification.warning({
+        top: 92,
+        message: '鏈幏鍙栧埌璁㈠崟ID锛�',
+        duration: 5
+      })
+    }
+  }
+
+  getOrder = (Id) => {
+    let param = {
+      func: 's_get_weixin_pay_native',
+      ID: Id,
+      sandbox: 'Y'
+    }
+
+    param.LTextOut = md5(param.ID + window.GLOB.appkey)
+    param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
+    param.secretkey = Utils.encrypt(param.LTextOut, param.timestamp)
+
+    Api.getLocalConfig(param).then(res => {
+      if (res.status) {
+        this.setState({
+          orderNo: res.out_trade_no,
+          total: res.amount ? res.amount.total : '',
+          unit: res.amount && res.amount.currency === 'CNY' ? '鍏�' : '鍏�',
+        })
+
+        if (!res.out_trade_no) {
+          notification.warning({
+            top: 10,
+            message: '鏈幏鍙栧埌璁㈠崟鍙凤紒',
+            duration: 5
+          })
+          return
+        } else if (!res.appid) {
+          notification.warning({
+            top: 10,
+            message: '鏈幏鍙栧埌搴旂敤ID锛�',
+            duration: 5
+          })
+          return
+        }
+
+        Api.getWxNativePay({ 'out_biz_no': res.out_trade_no, 'out_open_id': res.appid }).then(result => {
+          if (result.qrcode) {
+            this.setState({
+              qrcode: result.qrcode
+            })
+          } else {
+            notification.warning({
+              top: 10,
+              message: result.msg || '鏈幏鍙栧埌鏀粯鐮侊紒',
+              duration: 5
+            })
+          }
+        })
+      } else {
+        notification.warning({
+          top: 10,
+          message: res.message,
+          duration: 5
+        })
+      }
     })
   }
 
+  onChange = () => {
+
+  }
+
   render () {
+    const { logo, name, orderNo, icp, copyRight, total, unit, qrcode } = this.state
+
     return (
       <div className="mk-pay-container">
         <div className="mk-pay-box">
-          <div className="pay-tip">璇锋偍灏藉揩鏀粯锛屼互渚胯鍗曞揩閫熷鐞嗭紒</div>
-          <div className="mk-pay-content">
-            <div>鏀粯鏂瑰紡:</div>
+          <header>
+            <img className="plat-logo" src={logo} alt=""/>
+            <div className="user-name">{name}</div>
+          </header>
+          <div className="pay-tip">
+            <span>璇锋偍灏藉揩鏀粯锛屼互渚胯鍗曞揩閫熷鐞嗭紒璁㈠崟鍙凤細{orderNo}</span>
+            <span className="pay-total">搴斾粯閲戦<span>{total}</span>{unit}</span>
           </div>
-          <div className="mk-pay-msg">
-            <div>搴斾粯閲戦:</div>
+          <div className="mk-pay-content">
+            <div className="mk-pay-type">
+              <span className="tip">鏀粯鏂瑰紡锛�</span>
+              <Radio.Group onChange={this.onChange} value="weixin">
+                <Radio value="weixin">寰俊鏀粯</Radio>
+              </Radio.Group>
+            </div>
+            <div className="qrcode-box">
+              <p>浜岀淮鐮佹湁鏁堟椂闀�5鍒嗛挓锛岃繃鏈熷悗璇峰埛鏂伴〉闈㈤噸鏂拌幏鍙栦簩缁寸爜銆�</p>
+              <QRCode
+                value={qrcode}
+                size={230}
+                fgColor="#000000"
+                // imageSettings={{
+                //   src: '',
+                //   height: 60,
+                //   width: 60,
+                //   excavate: true
+                // }}
+              />
+              <div className="qrcode-tip">
+                <img src={WeiXinScan} alt=""/>
+                <div>
+                  <p>璇蜂娇鐢ㄥ井淇℃壂涓�鎵�</p>
+                  <p>鎵弿浜岀淮鐮佹敮浠�</p>
+                </div>
+              </div>
+            </div>
+            <img className="weixin-scan" src={WeiXinPay} alt=""/>
+          </div>
+          <div className="mk-pay-bottom">
+            {copyRight ? <p dangerouslySetInnerHTML={{ __html: copyRight.replace(/\s/ig, '&nbsp;') }}></p> : null}
+            {icp ? <p dangerouslySetInnerHTML={{ __html: icp.replace(/\s/ig, '&nbsp;') }}></p> : null}
           </div>
         </div>
       </div>
diff --git a/src/views/pay/index.scss b/src/views/pay/index.scss
index ac98e59..9431c9d 100644
--- a/src/views/pay/index.scss
+++ b/src/views/pay/index.scss
@@ -6,28 +6,103 @@
   
   .mk-pay-box {
     margin: 0 auto;
-    width: 80vw;
+    width: 1000px;
     height: calc(100vh - 40px);
-    margin-top: 20px;
-    background: #ffffff;
+    // background: #ffffff;
     padding: 15px 20px;
     // box-shadow: 0px 0px 3px #bcbcbc;
 
+    header {
+      .plat-logo {
+        max-width: 180px;
+        max-height: 40px;
+      }
+      .user-name {
+        float: right;
+        font-size: 16px;
+        line-height: 35px;
+      }
+    }
+
     .pay-tip {
-      color: #1890ff;
-      font-size: 15px;
-      margin-bottom: 20px;
+      font-size: 13px;
+      margin-top: 25px;
+      margin-bottom: 4vh;
+
+      .pay-total {
+        float: right;
+        span {
+          color: red;
+          margin: 0 5px;
+        }
+      }
+    }
+
+    .mk-pay-type {
+      margin: 0px 0px 10px 20px;
+      padding-top: 20px;
+      .tip {
+        margin-right: 5px;
+      }
     }
 
     .mk-pay-content {
-      display: inline-block;
-      width: 80%;
-      height: calc(100% - 40px);
+      min-height: 470px;
+      box-shadow: 0px 0px 40px #dfdfdf;
+      margin-bottom: 6vh;
+      .qrcode-box {
+        display: inline-block;
+        width: 50%;
+        text-align: center;
+        p {
+          font-size: 12px;
+          margin-top: 10px;
+        }
+        canvas {
+          padding: 15px;
+          border: 1px solid #dddddd;
+        }
+        .qrcode-tip {
+          background: #ff7674;
+          width: 230px;
+          margin: 10px auto;
+          img {
+            width: 40px;
+            margin: 4px;
+            vertical-align: top;
+          }
+          div {
+            display: inline-block;
+            margin-top: 8px;
+            margin-left: 10px;
+        
+            p {
+              margin: 0;
+              color: #ffffff;
+              text-align: left;
+            }
+          }
+        }
+      }
+      .weixin-scan {
+        vertical-align: top;
+        width: 280px;
+        margin-top: 20px;
+      }
     }
     .mk-pay-msg {
       display: inline-block;
       width: 20%;
       height: calc(100% - 40px);
     }
+    .mk-pay-bottom {
+      border-top: 1px solid #dddddd;
+      padding-top: 10px;
+      p {
+        margin-bottom: 5px;
+        text-align: center;
+        font-size: 12px;
+      }
+    }
   }
 }
\ No newline at end of file

--
Gitblit v1.8.0