li.shaoyi 2 anos atrás
pai
commit
6c33d61de3

+ 4 - 1
README.md

@@ -25,4 +25,7 @@ See [Configuration Reference](https://cli.vuejs.org/config/).
 
 
 ## 注意事项
-除 ./src/packages 文件夹内禁止引入UI组件库
+除 ./src/packages 文件夹内禁止引入UI组件库
+
+https://blog.csdn.net/qq_40323256/article/details/123809155
+npx pbjs -t json-module -w commonjs -o src/services/socket/trade/protobuf/thj.js public/proto/thj.proto

+ 67 - 0
package-lock.json

@@ -11,6 +11,7 @@
         "@tinymce/tinymce-vue": "^5.0.0",
         "@vant/compat": "^1.0.0",
         "axios": "^0.26.1",
+        "clipboard": "^2.0.11",
         "core-js": "^3.8.3",
         "crypto-js": "^4.1.1",
         "default-passive-events": "^2.0.0",
@@ -4542,6 +4543,16 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/clipboard": {
+      "version": "2.0.11",
+      "resolved": "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz",
+      "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
+      "dependencies": {
+        "good-listener": "^1.2.2",
+        "select": "^1.1.2",
+        "tiny-emitter": "^2.0.0"
+      }
+    },
     "node_modules/clipboardy": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz",
@@ -5448,6 +5459,11 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/delegate": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz",
+      "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
+    },
     "node_modules/depd": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -7025,6 +7041,14 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
+    "node_modules/good-listener": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz",
+      "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
+      "dependencies": {
+        "delegate": "^3.1.2"
+      }
+    },
     "node_modules/graceful-fs": {
       "version": "4.2.10",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
@@ -10436,6 +10460,11 @@
         "url": "https://opencollective.com/webpack"
       }
     },
+    "node_modules/select": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz",
+      "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
+    },
     "node_modules/select-hose": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -11324,6 +11353,11 @@
       "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
       "dev": true
     },
+    "node_modules/tiny-emitter": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+      "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
+    },
     "node_modules/tinymce": {
       "version": "6.0.3",
       "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-6.0.3.tgz",
@@ -16143,6 +16177,16 @@
       "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==",
       "dev": true
     },
+    "clipboard": {
+      "version": "2.0.11",
+      "resolved": "https://registry.npmmirror.com/clipboard/-/clipboard-2.0.11.tgz",
+      "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==",
+      "requires": {
+        "good-listener": "^1.2.2",
+        "select": "^1.1.2",
+        "tiny-emitter": "^2.0.0"
+      }
+    },
     "clipboardy": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz",
@@ -16798,6 +16842,11 @@
         "object-keys": "^1.1.1"
       }
     },
+    "delegate": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmmirror.com/delegate/-/delegate-3.2.0.tgz",
+      "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
+    },
     "depd": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -17978,6 +18027,14 @@
         "slash": "^3.0.0"
       }
     },
+    "good-listener": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmmirror.com/good-listener/-/good-listener-1.2.2.tgz",
+      "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==",
+      "requires": {
+        "delegate": "^3.1.2"
+      }
+    },
     "graceful-fs": {
       "version": "4.2.10",
       "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
@@ -20477,6 +20534,11 @@
         "ajv-keywords": "^3.5.2"
       }
     },
+    "select": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/select/-/select-1.1.2.tgz",
+      "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA=="
+    },
     "select-hose": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -21161,6 +21223,11 @@
       "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
       "dev": true
     },
+    "tiny-emitter": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+      "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
+    },
     "tinymce": {
       "version": "6.0.3",
       "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-6.0.3.tgz",

+ 1 - 0
package.json

@@ -13,6 +13,7 @@
     "@tinymce/tinymce-vue": "^5.0.0",
     "@vant/compat": "^1.0.0",
     "axios": "^0.26.1",
+    "clipboard": "^2.0.11",
     "core-js": "^3.8.3",
     "crypto-js": "^4.1.1",
     "default-passive-events": "^2.0.0",

+ 23 - 0
public/proto/thj.proto

@@ -851,6 +851,7 @@ message SpotPresaleTransferListingReq {
 	optional uint32 ClientType = 5; // 终端类型
 	optional string ClientSerialNo = 6; // 客户端流水号
 }
+
 // 铁合金现货预售转让挂牌接口响应
 message SpotPresaleTransferListingRsp {
 	optional MessageHead Header = 1; // 消息头
@@ -861,6 +862,7 @@ message SpotPresaleTransferListingRsp {
 	optional uint64 WRTradeDetailID = 6; // 采购成交单ID
 	optional string ClientSerialNo = 7; // 客户端流水号
 }
+
 // 铁合金现货预售转让撤销接口请求
 message SpotPresaleTransferCancelReq {
 	optional MessageHead Header = 1;
@@ -869,6 +871,7 @@ message SpotPresaleTransferCancelReq {
 	optional uint32 ClientType = 4; // 终端类型
 	optional string ClientSerialNo = 5; // 客户端流水号
 }
+
 // 铁合金现货预售转让撤销接口响应
 message SpotPresaleTransferCancelRsp {
 	optional MessageHead Header = 1; // 消息头
@@ -878,6 +881,7 @@ message SpotPresaleTransferCancelRsp {
 	optional uint64 WRTradeDetailID = 5; // 采购成交单ID
 	optional string ClientSerialNo = 6; // 客户端流水号
 }
+
 // 铁合金现货预售转让摘牌接口请求
 message SpotPresaleTransferDestingReq {
 	optional MessageHead Header = 1;
@@ -887,6 +891,7 @@ message SpotPresaleTransferDestingReq {
 	optional uint32 ClientType = 5; // 终端类型
 	optional string ClientSerialNo = 6; // 客户端流水号
 }
+
 // 铁合金现货预售转让摘牌接口响应
 message SpotPresaleTransferDestingRsp {
 	optional MessageHead Header = 1; // 消息头
@@ -896,6 +901,7 @@ message SpotPresaleTransferDestingRsp {
 	optional uint64 TransferID = 5; // 协议转让ID
 	optional string ClientSerialNo = 6; // 客户端流水号
 }
+
 // 铁合金收益支取申请接口请求
 message THJProfitDrawApplyReq {
 	optional MessageHead Header = 1;
@@ -907,6 +913,7 @@ message THJProfitDrawApplyReq {
 	optional uint32 ClientType = 7; // 终端类型,如果申请来源为2则填写
 	optional string ClientSerialNo = 8; // 客户端流水号
 }
+
 // 铁合金收益支取申请接口响应
 message THJProfitDrawApplyRsp {
 	optional MessageHead Header = 1; // 消息头
@@ -915,4 +922,20 @@ message THJProfitDrawApplyRsp {
 	optional uint32 UserID = 4; // 用户ID
 	optional uint64 ApplyID = 5; // 申请ID
 	optional string ClientSerialNo = 6; // 客户端流水号
+}
+
+// 交易商头像请求
+message DealerHeadReq {
+	optional MessageHead Header = 1;
+		optional uint64 ClientSerialID = 2; // 客户端唯一ID
+		optional uint64 UserId = 3; // 用户ID
+		optional string HeadUrl = 4; // 头像地址
+		optional uint32 OptType = 5; // 操作类型1新增2修改3删除
+}
+// 交易商头像应答
+message DealerHeadRsp {
+	optional MessageHead Header = 1; // 消息头
+	optional int32 RetCode = 2; // 返回码
+	optional string RetDesc = 3; // 描述信息
+		optional uint64 ClientSerialID = 4; // 客户端唯一ID
 }

+ 10 - 7
src/constants/funcode.ts

@@ -18,6 +18,9 @@ export enum FunCode {
     InvestorDelReq = 1900553, // 投资者销户申请请求
     InvestorDelRsp = 1900554, // 投资者销户申请请求响应
 
+    DealerHeadReq = 1900635, // 交易商头像请求
+    DealerHeadRsp = 1900636, // 交易商头像应答
+
     t2bBankSignReq = 589825, // 签约请求
     t2bBankSignRsp = 589826, // 签约应答
     t2bBankCancelSignReq = 589827, // 解约请求
@@ -74,11 +77,11 @@ export enum FunCode {
     HdWRDealOrderReq = 1441809,                       /// 持仓单摘牌请求
     HdWRDealOrderRsp = 1441810,                       /// 持仓单摘牌应答
     SpotPresaleTransferListingReq = 1441859,          /// 铁合金现货预售转让挂牌接口请求(0, 22, 67)
-	SpotPresaleTransferListingRsp = 1441860,          /// 铁合金现货预售转让挂牌接口响应(0, 22, 68)
-	SpotPresaleTransferCancelReq = 1441867,           /// 铁合金现货预售转让撤销接口请求(0, 22, 75)
-	SpotPresaleTransferCancelRsp = 1441868,           /// 铁合金现货预售转让撤销接口响应(0, 22, 76)
-	SpotPresaleTransferDestingReq = 1441869,          /// 铁合金现货预售转让摘牌接口请求(0, 22, 77)
-	SpotPresaleTransferDestingRsp = 1441870,          /// 铁合金现货预售转让摘牌接口响应(0, 22, 78)
-	THJProfitDrawApplyReq = 1441871,                  /// 铁合金收益支取申请接口请求(0, 22, 79)
-	THJProfitDrawApplyRsp = 1441872,                  /// 铁合金收益支取申请接口响应(0, 22, 80)
+    SpotPresaleTransferListingRsp = 1441860,          /// 铁合金现货预售转让挂牌接口响应(0, 22, 68)
+    SpotPresaleTransferCancelReq = 1441867,           /// 铁合金现货预售转让撤销接口请求(0, 22, 75)
+    SpotPresaleTransferCancelRsp = 1441868,           /// 铁合金现货预售转让撤销接口响应(0, 22, 76)
+    SpotPresaleTransferDestingReq = 1441869,          /// 铁合金现货预售转让摘牌接口请求(0, 22, 77)
+    SpotPresaleTransferDestingRsp = 1441870,          /// 铁合金现货预售转让摘牌接口响应(0, 22, 78)
+    THJProfitDrawApplyReq = 1441871,                  /// 铁合金收益支取申请接口请求(0, 22, 79)
+    THJProfitDrawApplyRsp = 1441872,                  /// 铁合金收益支取申请接口响应(0, 22, 80)
 } 

+ 25 - 0
src/directives/copy/index.ts

@@ -0,0 +1,25 @@
+import { Directive } from 'vue'
+import Clipboard from 'clipboard'
+
+/**
+ * 复制文本到剪贴板
+ */
+export const copy: Directive = {
+    mounted(el, binding) {
+        const fn = binding.value
+        el.clipboard = new Clipboard(el)
+        el.clipboard.on('success', () => {
+            if (fn instanceof Function) {
+                fn(true)
+            }
+        })
+        el.clipboard.on('error', () => {
+            if (fn instanceof Function) {
+                fn(false)
+            }
+        })
+    },
+    unmounted(el) {
+        el.clipboard.destroy()
+    }
+}

+ 4 - 2
src/directives/index.ts

@@ -1,9 +1,11 @@
 import { App } from 'vue'
 import { validate, rules } from './validate'
+import { copy } from './copy'
 
 const install = (app: App) => {
-    app.directive('rules', rules);
-    app.directive('validate', validate);
+    app.directive('rules', rules)
+    app.directive('validate', validate)
+    app.directive('copy', copy)
 }
 
 export default {

+ 1 - 1
src/filters/index.ts

@@ -17,7 +17,7 @@ export function getUrl(url: string, base?: string) {
  * 获取图片地址
  * @param fileUrl 
  */
-export function getImageUrl(fileUrl: string) {
+export function getImageUrl(fileUrl?: string) {
     if (fileUrl) {
         const url = getUrl(fileUrl)
         return url.href

+ 43 - 0
src/packages/mobile/components/base/uploader/index.vue

@@ -0,0 +1,43 @@
+<template>
+    <Uploader v-model="fileList" :max-count="1" :max-size="5 * 1024 * 1024" @oversize="onOversize"
+        :after-read="afterRead" @delete="onDelete" />
+</template>
+
+<script lang="ts" setup>
+import { ref } from 'vue'
+import { showFailToast, Uploader, UploaderFileListItem } from 'vant'
+import { getServiceUrl } from '@/services/http'
+import axios from 'axios'
+
+const emit = defineEmits(['success'])
+const fileList = ref<UploaderFileListItem[]>([])
+
+const onOversize = () => {
+    showFailToast('图片大小不能超过 5Mb')
+}
+
+// eslint-disable-next-line
+const afterRead = (file: any) => {
+    const data = new FormData()
+    data.append('file', file.file)
+
+    file.status = 'uploading'
+    file.message = '上传中...'
+    axios.post(getServiceUrl('uploadUrl'), data).then(res => {
+        if (res.status == 200) {
+            file.status = 'success'
+            file.message = '上传成功'
+            if (res.data.length) {
+                emit('success', res.data[0].filePath)
+            }
+        } else {
+            file.status = 'failed'
+            file.message = '上传失败'
+        }
+    })
+}
+
+const onDelete = () => {
+    emit('success', '')
+}
+</script>

+ 5 - 0
src/packages/mobile/router/index.ts

@@ -72,6 +72,11 @@ const routes: Array<RouteRecordRaw> = [
         name: "UserPassword",
         component: () => import("../views/user/password/index.vue"),
       },
+      {
+        path: "avatar",
+        name: "UserAvatar",
+        component: () => import("../views/user/avatar/index.vue"),
+      },
     ],
   },
   {

+ 11 - 51
src/packages/mobile/views/account/certification/index.vue

@@ -16,12 +16,12 @@
                     :rules="formRules.cardnum" />
                 <Field name="cardfrontphotourl" label="证件正面照片" :rules="formRules.cardfrontphotourl">
                     <template #input>
-                        <Uploader v-model="frontList" max-count="1" :after-read="b_afterRead" />
+                        <app-uploader @success="b_afterRead" />
                     </template>
                 </Field>
                 <Field name="cardbackphotourl" label="证件反面照片" :rules="formRules.cardbackphotourl">
                     <template #input>
-                        <Uploader v-model="backList" max-count="1" :after-read="f_afterRead" />
+                        <app-uploader @success="f_afterRead" />
                     </template>
                 </Field>
             </CellGroup>
@@ -36,68 +36,29 @@
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, computed, ref } from 'vue'
-import { CellGroup, Button, Field, Form, FormInstance, Uploader, showFailToast, FieldRule } from 'vant'
+import { shallowRef, computed } from 'vue'
+import { CellGroup, Button, Field, Form, FormInstance, showFailToast, FieldRule } from 'vant'
 import { addAuthReq } from '@/business/user'
 import { fullloading, dialog } from '@/utils/vant';
 import { getCertificateTypeList } from "@/constants/account";
 import AppSelect from '@mobile/components/base/select/index.vue'
 import { useNavigation } from '@/hooks/navigation'
-import axios from 'axios';
-import { getServiceUrl } from '@/services/http';
+import AppUploader from '@mobile/components/base/uploader/index.vue'
 
 const formRef = shallowRef<FormInstance>()
 const { formData, formSubmit } = addAuthReq()
 const { router } = useNavigation()
 
-/// 证件正面地址
-const backList = ref([]);
-/// 证件背面地址
-const frontList = ref([]);
 /// 获取对应的证件枚举类型
 const enums = computed(() => { return getCertificateTypeList().map(obj => { return { label: obj.label, value: obj.value } }) })
 
-const b_afterRead = (file: any) => {
-    file.status = 'uploading';
-    file.message = '上传中...';
-
-    var data = new FormData()
-    data.append('file', file.file)
-    let config = { headers: { "Content-type": "multipart/form-data" } }
-
-    /// 图片上传
-    axios.post(getServiceUrl('uploadUrl'), data, config).then(res => {
-        if (res.status == 200) {
-            file.status = 'success';
-            file.message = '上传成功';
-            formData.cardfrontphotourl = res.data[0].filePath
-        } else {
-            file.status = 'failed';
-            file.message = '上传失败';
-        }
-    })
-};
-
-const f_afterRead = (file: any) => {
-    file.status = 'uploading';
-    file.message = '上传中...';
-
-    var data = new FormData()
-    data.append('file', file.file)
-    let config = { headers: { "Content-type": "multipart/form-data" } }
+const b_afterRead = (filePath: string) => {
+    formData.cardfrontphotourl = filePath
+}
 
-    /// 图片上传
-    axios.post(getServiceUrl('uploadUrl'), data, config).then(res => {
-        if (res.status == 200) {
-            file.status = 'success';
-            file.message = '上传成功';
-            formData.cardbackphotourl = res.data[0].filePath
-        } else {
-            file.status = 'failed';
-            file.message = '上传失败';
-        }
-    })
-};
+const f_afterRead = (filePath: string) => {
+    formData.cardbackphotourl = filePath
+}
 
 // 表单验证规则
 const formRules: { [key in keyof Model.AddAuthReq]?: FieldRule[] } = {
@@ -132,5 +93,4 @@ const onSubmit = () => {
         })
     })
 }
-
 </script>

+ 35 - 0
src/packages/mobile/views/bank/wallet/components/deposit/index.less

@@ -0,0 +1,35 @@
+.bank-wallet-deposit {
+    .g-form__time {
+        color: #999;
+        padding-left: 15px;
+    }
+
+    .g-form__bank {
+        padding: 16px;
+
+        table {
+            width: 100%;
+            font-size: .24rem;
+            border: 1px dashed #ddd;
+            border-radius: .1rem;
+
+            td {
+                &:not(:first-child) {
+                    text-align: right;
+                }
+
+                span {
+                    &:first-child {
+                        color: #999;
+                    }
+                }
+
+                button {
+                    background-color: #e1e1e1;
+                    border-radius: .1rem;
+                    padding: .04rem .2rem;
+                }
+            }
+        }
+    }
+}

+ 63 - 50
src/packages/mobile/views/bank/wallet/components/deposit/index.vue

@@ -1,13 +1,12 @@
 <template>
-    <app-view class="g-form">
+    <app-view class="g-form bank-wallet-deposit">
         <Form ref="formRef" class="g-form__container" @submit="formSubmit">
             <CellGroup inset>
                 <Field type="number" v-model="formData.Amount" label="充值金额" placeholder="请填写充值金额"
                     :rules="formRules.Amount" />
-                <Field label="凭证" :rules="formRules.fileList">
+                <Field label="凭证" :rules="formRules.filePath">
                     <template #input>
-                        <Uploader v-model="fileList" name="fileList" :max-size="5 * 1024 * 1024" @oversize="onOversize"
-                            max-count="1" :after-read="afterRead" />
+                        <app-uploader @success="onUploadSuccess" />
                     </template>
                 </Field>
             </CellGroup>
@@ -15,6 +14,45 @@
         <div class="g-form__time">
             <label>充值提现时间:{{ start }}-{{ end }}</label>
         </div>
+        <div class="g-form__bank">
+            <table cellspacing="10" cellpadding="0">
+                <tr>
+                    <td>
+                        <span>企业名称:</span>
+                        <span>上海徽行供应链有限公司</span>
+                    </td>
+                    <td>
+                        <button type="button" data-clipboard-text="上海徽行供应链有限公司" v-copy="onCopy">复制</button>
+                    </td>
+                </tr>
+                <tr>
+                    <td colspan="2">
+                        <span>开户银行:</span>
+                        <span>中信银行上海虹口支行</span>
+                    </td>
+                </tr>
+                <tr>
+                    <td>
+                        <span>银行账户:</span>
+                        <span>8110201012101533442</span>
+                    </td>
+                    <td>
+                        <button ref="copy2" type="button" data-clipboard-text="8110201012101533442"
+                            v-copy="onCopy">复制</button>
+                    </td>
+                </tr>
+                <tr>
+                    <td colspan="2">
+                        <span>(汇款备注:预付货款或合同转让款)</span>
+                    </td>
+                </tr>
+                <tr>
+                    <td colspan="2">
+                        <span>电话: 021-63138889, 13681901188</span>
+                    </td>
+                </tr>
+            </table>
+        </div>
         <template #footer>
             <div class="g-form__footer">
                 <Button round block type="primary" @click="formRef?.submit()">确定</Button>
@@ -24,66 +62,47 @@
 </template>
 
 <script lang="ts" setup>
-import { ref } from 'vue'
-import { Form, Field, CellGroup, Button, Uploader, FieldRule, FormInstance, showFailToast } from 'vant'
+import { shallowRef } from 'vue'
+import { Form, Field, CellGroup, Button, FieldRule, FormInstance, showFailToast, showSuccessToast } from 'vant'
 import { useDoDeposit } from '@/business/bank'
-import { fullloading, dialog } from '@/utils/vant';
+import { fullloading, dialog } from '@/utils/vant'
 import { useNavigation } from '@/hooks/navigation'
-import axios from 'axios';
-import { getServiceUrl } from '@/services/http';
 import { useUserStore } from '@/stores'
+import AppUploader from '@mobile/components/base/uploader/index.vue'
 
-const formRef = ref<FormInstance>()
+const formRef = shallowRef<FormInstance>()
 const { formData, onSubmit, extendInfo } = useDoDeposit()
 const { router } = useNavigation()
 const { getSystemParamValue } = useUserStore()
 const start = getSystemParamValue('012')
 const end = getSystemParamValue('013')
 
-/// 证件正面地址
-const fileList = ref([]);
-
-const afterRead = (file: any) => {
-    file.status = 'uploading';
-    file.message = '上传中...';
-
-    var data = new FormData()
-    data.append('file', file.file)
-    const config = { headers: { "Content-type": "multipart/form-data" } }
-
-    /// 图片上传
-    axios.post(getServiceUrl('uploadUrl'), data, config).then(res => {
-        /// 上传成功
-        if (res.status == 200) {
-            file.status = 'success';
-            file.message = '上传成功';
-            /// 赋值
-            extendInfo.certificate_photo_url = res.data[0].filePath
-        } else {
-            file.status = 'failed';
-            file.message = '上传失败';
-        }
-    })
-};
-
-const onOversize = () => {
-    showFailToast('图片大小不能超过 5Mb')
-};
-
 // 表单验证规则
-const formRules: { [key in keyof Proto.t2bBankDepositReq | 'fileList']?: FieldRule[] } = {
+const formRules: { [key in keyof Proto.t2bBankDepositReq | 'filePath']?: FieldRule[] } = {
     Amount: [{
         required: true,
         message: '请填写充值金额',
     }],
-    fileList: [{
+    filePath: [{
         message: '请上传转账凭证',
         validator: () => {
-            return fileList.value.length > 0
+            return !!extendInfo.certificate_photo_url
         }
     }]
 }
 
+const onCopy = (status: boolean) => {
+    if (status) {
+        showSuccessToast('复制成功')
+    } else {
+        showFailToast('复制失败')
+    }
+}
+
+const onUploadSuccess = (filePath: string) => {
+    extendInfo.certificate_photo_url = filePath
+}
+
 const formSubmit = () => {
     fullloading((hideLoading) => {
         onSubmit().then(() => {
@@ -96,14 +115,8 @@ const formSubmit = () => {
         })
     })
 }
-
 </script>
 
 <style lang="less">
-.g-form {
-    &__time {
-        color: #999;
-        padding-left: 15px;
-    }
-}
+@import './index.less';
 </style>

+ 3 - 3
src/packages/mobile/views/bank/wallet/components/withdraw/index.less

@@ -1,9 +1,9 @@
 .bank-wallet-withdraw {
     .form-field {
         .van-field__control {
-            display       : flex;
+            display: flex;
             flex-direction: column;
-            align-items   : flex-start;
+            align-items: flex-start;
         }
 
         &__tips {
@@ -11,7 +11,7 @@
         }
     }
 
-    &__time {
+    .g-form__time {
         color: #999;
         padding-left: 15px;
     }

+ 7 - 0
src/packages/mobile/views/home/components/main/index.less

@@ -96,6 +96,13 @@
                 span {
                     font-size: .26rem;
                     font-weight: bold;
+
+                    +span {
+                        color: #999;
+                        font-size: .24rem;
+                        font-weight: normal;
+                        margin-left: .1rem;
+                    }
                 }
             }
         }

+ 56 - 4
src/packages/mobile/views/home/components/main/index.vue

@@ -43,7 +43,31 @@
           </li>
         </ul>
       </app-block>
-      <app-block class="home-main__market" v-if="dataList.length">
+      <app-block class="home-main__market" v-if="spotQuoteList.length">
+        <section class="scrollbar">
+          <h4 class="scrollbar-title">
+            <img src="@mobile/assets/icons/spot.png" />
+            <span>现货行情</span>
+            <span>({{ currentSpotQuote.spotmonth }})</span>
+          </h4>
+          <Swipe :autoplay="8000" :show-indicators="false" :touchable="false" vertical @change="onSpotChange">
+            <SwipeItem v-for="(item, i) in spotQuoteList" :key="i">
+              <ul @click="openNewsDetails(item.relatedid)">
+                <li>
+                  <span>{{ item.spotsrc }}</span>
+                </li>
+                <li>
+                  <span>{{ item.spotname }}招标价 </span>
+                  <span class="g-color--up">{{ item.spotprice }} 元/吨</span>
+                </li>
+                <li>
+                  <span>采购量 </span>
+                  <span class="g-color--up">{{ item.spotqty }} 吨</span>
+                </li>
+              </ul>
+            </SwipeItem>
+          </Swipe>
+        </section>
         <section class="scrollbar">
           <h4 class="scrollbar-title">
             <img src="@mobile/assets/icons/futures.png" />
@@ -56,7 +80,8 @@
               <ul>
                 <li>{{ goodsname }}</li>
                 <li style="color:#999">{{ formatDate(lasttime, 'HH:mm') }}</li>
-                <li :class="handlePriceColor(last, presettle)">{{ handleNumberValue(formatDecimal(last, decimalplace)) }}
+                <li :class="handlePriceColor(last, presettle)">{{ handleNumberValue(formatDecimal(last, decimalplace))
+                }}
                 </li>
                 <li :class="handlePriceColor(last, presettle)">{{ handleNumberValue(formatDecimal(change, decimalplace))
                 }}</li>
@@ -98,7 +123,7 @@
 </template>
 
 <script lang="ts" setup>
-import { shallowRef } from "vue";
+import { shallowRef, computed } from "vue";
 import { Cell, CellGroup, Swipe, SwipeItem, PullRefresh } from "vant";
 import { formatDecimal, getImageUrl, formatDate, handlePriceColor, parsePercent, handleNumberValue, changeUnit } from "@/filters";
 import { useNavigation } from "@/hooks/navigation";
@@ -106,15 +131,36 @@ import { queryImageConfigs } from "@/services/api/common";
 import { querySiteColumnDetail } from "@/services/api/news";
 import { useFuturesList } from "@/business/market";
 import { queryMarketRun } from "@/services/api/goods";
+import { queryThjSpotQuoteConfig } from "@/services/api/market";
 
-const { routerTo } = useNavigation();
+const { router, routerTo } = useNavigation();
 const { dataList, quoteSubscribe } = useFuturesList();
 const refreshing = shallowRef(false); // 是否处于加载中状态
 const topBanners = shallowRef<Model.ImageConfigsRsp[]>([]); // 轮播图列表
 const bodyBanners = shallowRef<Model.ImageConfigsRsp[]>([]); // 轮播图列表
 const newsList = shallowRef<Model.SiteColumnDetailRsp[]>([]); // 资讯列表
+const spotQuoteList = shallowRef<Model.ThjSpotQuoteConfigRsp[]>([]); // 现货行情
+const spotQuoteIndex = shallowRef(0) // 当前现货行情索引
 const marketRun = shallowRef<Partial<Model.MarketRunRsp>>({}); // 市场
 
+// 当前现货行情
+const currentSpotQuote = computed(() => spotQuoteList.value[spotQuoteIndex.value])
+
+// 打开新闻详情
+const openNewsDetails = (id: number) => {
+  if (id) {
+    const details = newsList.value.find((e) => e.id === id)
+    if (details) {
+      router.push({ name: 'news-details', params: { item: JSON.stringify(details) } })
+    }
+  }
+}
+
+// 现货行情轮播变化
+const onSpotChange = (index: number) => {
+  spotQuoteIndex.value = index
+}
+
 // 下拉刷新
 const onRefresh = () => {
   // 市场信息
@@ -156,6 +202,12 @@ queryImageConfigs({
   },
 });
 
+queryThjSpotQuoteConfig({
+  success: (res) => {
+    spotQuoteList.value = res.data
+  },
+})
+
 onRefresh();
 quoteSubscribe.start();
 </script>

+ 12 - 4
src/packages/mobile/views/mine/main/index.vue

@@ -7,8 +7,8 @@
       <div class="mine-header__wrapper">
         <div class="profile">
           <div class="profile-user">
-            <div class="profile-user__avatar">
-              <img class="g-image--avatar" src="" />
+            <div class="profile-user__avatar" @click="routerTo('UserAvatar')">
+              <img class="g-image--avatar" :src="userAvatar" />
             </div>
             <div class="profile-user__info">
               <div>
@@ -116,11 +116,12 @@
 </template>
 
 <script lang="ts" setup>
-import { shallowRef, onActivated } from 'vue'
+import { shallowRef, onActivated, computed } from 'vue'
 import { Cell, CellGroup, Button, Tag, showFailToast } from 'vant'
 import { fullloading, dialog } from '@/utils/vant'
+import { getImageUrl } from '@/filters'
 import { useNavigation } from '@/hooks/navigation'
-import { useLoginStore, useAccountStore, } from '@/stores'
+import { useLoginStore, useAccountStore, useUserStore } from '@/stores'
 import AppIconfont from '@mobile/components/base/iconfont/index.vue'
 import { useBankAccountSign } from '@/business/bank'
 import { queryUserAccount } from '@/services/api/account'
@@ -129,11 +130,18 @@ import eventBus from '@/services/bus'
 
 const { router, routerTo } = useNavigation()
 const { getUserId, getLoginId, getFirstAccountId } = useLoginStore()
+const { userData } = useUserStore()
 const { getBankAccountList, bankInfo } = useBankAccountSign()
 const { accountInfo, freezeMargin, avaiableMoney } = useAccountStore()
 const authStatus = shallowRef(AuthStatus.Uncertified) // 实名认证状态
 const headerRef = shallowRef<HTMLDivElement>()
 
+// 用户头像
+const userAvatar = computed(() => {
+  const file = userData.value.userInfo?.headurl
+  return file ? getImageUrl(file) : ''
+})
+
 const onReady = (el: HTMLDivElement) => {
   // 设置背景图位置
   headerRef.value?.style.setProperty('background-position', `0 -${el.clientHeight}px`)

+ 1 - 1
src/packages/mobile/views/rules/ccwl/index.vue

@@ -27,7 +27,7 @@ import plus from '@/utils/h5plus'
 const asyncComponent = defineAsyncComponent(() => import('@mobile/components/base/html-panel/index.vue'))
 
 const download = () => {
-  plus.downloadFile('./html/yswtmb.docx')
+    plus.openFile('./html/yswtmb.docx')
 }
 </script>
 

+ 1 - 1
src/packages/mobile/views/rules/cght/index.vue

@@ -17,6 +17,6 @@ import { Button } from 'vant'
 import plus from '@/utils/h5plus'
 
 const download = () => {
-  plus.downloadFile('./html/ht_cg.docx')
+  plus.openFile('./html/ht_cg.docx')
 }
 </script>

+ 2 - 2
src/packages/mobile/views/rules/xhht/index.vue

@@ -20,7 +20,7 @@
 import { Button } from 'vant'
 import plus from '@/utils/h5plus'
 
-const download = (filePath:string) => {
-  plus.downloadFile(filePath)
+const download = (filePath: string) => {
+  plus.openFile(filePath)
 }
 </script>

+ 1 - 1
src/packages/mobile/views/rules/zrht/index.vue

@@ -17,6 +17,6 @@ import { Button } from 'vant'
 import plus from '@/utils/h5plus'
 
 const download = () => {
-  plus.downloadFile('./html/ht_zr.docx')
+  plus.openFile('./html/ht_zr.docx')
 }
 </script>

+ 71 - 0
src/packages/mobile/views/user/avatar/index.vue

@@ -0,0 +1,71 @@
+<template>
+    <app-view class="g-form">
+        <template #header>
+            <app-navbar title="头像" />
+        </template>
+        <Form ref="formRef" class="g-form__container" @submit="onSubmit">
+            <CellGroup inset>
+                <Field label="用户头像" :rules="formRules.headurl">
+                    <template #input>
+                        <app-uploader @success="onUploadSuccess" />
+                    </template>
+                </Field>
+            </CellGroup>
+        </Form>
+        <template #footer>
+            <div class="g-form__footer">
+                <Button round block type="primary" @click="formRef?.submit">确定</Button>
+            </div>
+        </template>
+    </app-view>
+</template>
+
+<script lang="ts" setup>
+import { shallowRef, reactive } from 'vue'
+import { CellGroup, Button, Field, Form, FormInstance, FieldRule, showFailToast } from 'vant'
+import { fullloading } from '@/utils/vant'
+import { useNavigation } from '@/hooks/navigation'
+import { updateUserHeadUrl } from '@/services/api/user'
+import { useLoginStore, useUserStore } from '@/stores'
+import AppUploader from '@mobile/components/base/uploader/index.vue'
+
+const { getUserId } = useLoginStore()
+const { getUserData } = useUserStore()
+const { router } = useNavigation()
+
+const formRef = shallowRef<FormInstance>()
+const formData = reactive<Model.UserHeadUrlReq>({
+    userid: getUserId(), // 用户ID
+    headurl: '', // 头像地址
+})
+
+// 表单验证规则
+const formRules: { [key in keyof Model.UserHeadUrlReq]?: FieldRule[] } = {
+    headurl: [{
+        message: '请上传头像',
+        validator: () => {
+            return !!formData.headurl
+        }
+    }],
+}
+
+const onUploadSuccess = (filePath: string) => {
+    formData.headurl = filePath
+}
+
+const onSubmit = () => {
+    fullloading((hideLoading) => {
+        updateUserHeadUrl({
+            data: formData,
+            success: () => {
+                hideLoading()
+                getUserData()
+                router.back()
+            },
+            fail: (err) => {
+                showFailToast(err)
+            }
+        })
+    })
+}
+</script>

+ 7 - 0
src/services/api/market/index.ts

@@ -13,4 +13,11 @@ export function querySpotGoodsPrice(params: HttpParams<{ req: Model.SpotGoodsPri
  */
 export function querySpotgoodsPrice(params: HttpParams<{ req: Model.SpotgoodsPriceReq, rsp: Model.SpotgoodsPriceRsp[] }>) {
     return httpRequest('/Ferroalloy/QuerySpotgoodsPrice', 'get', params);
+}
+
+/**
+ * 查询现货行情配置表
+ */
+export function queryThjSpotQuoteConfig(params: HttpParams<{ rsp: Model.ThjSpotQuoteConfigRsp[] }>) {
+    return httpRequest('/Ferroalloy/QueryThjSpotQuoteConfig', 'get', params);
 }

+ 14 - 0
src/services/api/user/index.ts

@@ -50,4 +50,18 @@ export function userReceiptInfo(params: TradeParams<Proto.UserReceiptInfoReq, Pr
  */
 export function delUserReceiptInfo(params: TradeParams<Proto.DelUserReceiptInfoReq, Proto.DelUserReceiptInfoRsp>) {
     return tradeServerRequest('DelUserReceiptInfoReq', 'DelUserReceiptInfoRsp', params);
+}
+
+/**
+ * 交易商头像
+ */
+export function dealerHead(params: TradeParams<Proto.DealerHeadReq, Proto.DealerHeadRsp>) {
+    return tradeServerRequest('DealerHeadReq', 'DealerHeadRsp', params);
+}
+
+/**
+ * 更新用户头像
+ */
+export function updateUserHeadUrl(params: HttpParams<{ req: Model.UserHeadUrlReq }>) {
+    return httpRequest('/User/UpdateUserHeadUrl', 'post', params);
 }

+ 25 - 10
src/services/index.ts

@@ -1,9 +1,7 @@
 import axios from 'axios'
+import plus from '@/utils/h5plus'
 
 export default new (class {
-    /** 应用配置信息 */
-    //private appConfig = axios('./config/appconfig.json')
-
     /** 服务配置信息 */
     config = {
         commSearchUrl: '',
@@ -44,19 +42,36 @@ export default new (class {
 
     /**
      * 初始化服务配置
+     * https://uniapp.dcloud.net.cn/tutorial/app-ios-uiwebview.html
      */
     private init(): Promise<typeof this.config> {
         this.isPending = true
         return new Promise((resolve, reject) => {
-            // 获取服务接口地址
-            axios('http://218.17.158.45:16021/cfg?key=test_thj').then((res) => {
-                this.config = res.data.data
-                this.isReady = true
-                resolve(this.config)
+            const getAppConfig = async () => {
+                const filePath = './config/appconfig.json'
+                if (plus.hasPlus()) {
+                    const res = await plus.getLocalFileContent(filePath)
+                    return JSON.parse(res)
+                } else {
+                    const res = await axios(filePath)
+                    return res.data
+                }
+            }
+
+            getAppConfig().then((res) => {
+                // 获取服务接口地址
+                axios(res.apiUrl).then((res) => {
+                    this.config = res.data.data
+                    this.isReady = true
+                    resolve(this.config)
+                }).catch(() => {
+                    reject('获取服务地址失败')
+                }).finally(() => {
+                    this.isPending = false
+                })
             }).catch(() => {
-                reject('获取服务配置地址失败')
-            }).finally(() => {
                 this.isPending = false
+                reject('加载配置文件失败')
             })
         })
     }

+ 120 - 0
src/services/socket/trade/protobuf/thj.js

@@ -7705,6 +7705,126 @@ var $root = ($protobuf.roots["default"] || ($protobuf.roots["default"] = new $pr
         }
       }
     }
+  },
+  DealerHeadReq: {
+    oneofs: {
+      _Header: {
+        oneof: [
+          "Header"
+        ]
+      },
+      _ClientSerialID: {
+        oneof: [
+          "ClientSerialID"
+        ]
+      },
+      _UserId: {
+        oneof: [
+          "UserId"
+        ]
+      },
+      _HeadUrl: {
+        oneof: [
+          "HeadUrl"
+        ]
+      },
+      _OptType: {
+        oneof: [
+          "OptType"
+        ]
+      }
+    },
+    fields: {
+      Header: {
+        type: "MessageHead",
+        id: 1,
+        options: {
+          proto3_optional: true
+        }
+      },
+      ClientSerialID: {
+        type: "uint64",
+        id: 2,
+        options: {
+          proto3_optional: true
+        }
+      },
+      UserId: {
+        type: "uint64",
+        id: 3,
+        options: {
+          proto3_optional: true
+        }
+      },
+      HeadUrl: {
+        type: "string",
+        id: 4,
+        options: {
+          proto3_optional: true
+        }
+      },
+      OptType: {
+        type: "uint32",
+        id: 5,
+        options: {
+          proto3_optional: true
+        }
+      }
+    }
+  },
+  DealerHeadRsp: {
+    oneofs: {
+      _Header: {
+        oneof: [
+          "Header"
+        ]
+      },
+      _RetCode: {
+        oneof: [
+          "RetCode"
+        ]
+      },
+      _RetDesc: {
+        oneof: [
+          "RetDesc"
+        ]
+      },
+      _ClientSerialID: {
+        oneof: [
+          "ClientSerialID"
+        ]
+      }
+    },
+    fields: {
+      Header: {
+        type: "MessageHead",
+        id: 1,
+        options: {
+          proto3_optional: true
+        }
+      },
+      RetCode: {
+        type: "int32",
+        id: 2,
+        options: {
+          proto3_optional: true
+        }
+      },
+      RetDesc: {
+        type: "string",
+        id: 3,
+        options: {
+          proto3_optional: true
+        }
+      },
+      ClientSerialID: {
+        type: "uint64",
+        id: 4,
+        options: {
+          proto3_optional: true
+        }
+      }
+    }
   }
 });
 

+ 12 - 0
src/types/model/market.d.ts

@@ -1,4 +1,16 @@
 declare namespace Model {
+    /** 查询现货行情配置表 响应 */
+    interface ThjSpotQuoteConfigRsp {
+        autoid: number;  // 自增ID(SEQ_THJ_SPOTQUOTECONFIG)
+        relatedid: number; // 关联新闻ID(Site_ColumnDetail)
+        spotmonth: string; // 现货月份(yyyy-MM)
+        spotname: string; // 现货名称
+        spotprice: string; // 现货招标价
+        spotqty: string; // 现货采购量
+        spotsrc: string; // 现货来源
+        updatetime: string; // 更新时间
+    }
+
     /** 查询行情-现货列表 请求 */
     interface SpotgoodsPriceReq {
         page: number; // 页码

+ 6 - 0
src/types/model/user.d.ts

@@ -1,4 +1,10 @@
 declare namespace Model {
+    /** 更新用户头像 请求 */
+    interface UserHeadUrlReq {
+        userid: number; // 用户ID
+        headurl: string;
+    }
+
     /** 查询收货地址信息 请求 */
     interface UserReceiveInfoReq {
         userid: number; // 用户ID

+ 17 - 0
src/types/proto/user.d.ts

@@ -2,6 +2,23 @@ import { IMessageHead } from '@/services/socket/trade/protobuf/proto'
 
 declare global {
     namespace Proto {
+        /** 交易商头像请求 */
+        interface DealerHeadReq {
+            Header?: IMessageHead;
+            ClientSerialID: number; // 客户端唯一ID
+            UserId: number; // 用户ID
+            HeadUrl: string; // 头像地址
+            OptType: number; // 操作类型1新增2修改3删除
+        }
+
+        /** 交易商头像应答 */
+        interface DealerHeadRsp {
+            Header?: IMessageHead;
+            RetCode: number; // 返回码
+            RetDesc: string; // 描述信息
+            ClientSerialID: number; // 客户端唯一ID
+        }
+
         /** 新增修改收货地址请求 */
         interface UserReceiveInfoReq {
             Header?: IMessageHead;

+ 30 - 25
src/utils/h5plus/index.ts

@@ -1,5 +1,7 @@
+/* eslint-disable */
+
 interface HTML5 extends Window {
-    plus?: any; // eslint-disable-line
+    plus?: any;
 }
 
 export default new (class {
@@ -16,7 +18,6 @@ export default new (class {
             const webview = plus.webview.currentWebview();
 
             plus.key.addEventListener('backbutton', () => {
-                // eslint-disable-next-line
                 webview.canBack((e: any) => {
                     // 判断能否继续返回
                     if (e.canBack) {
@@ -38,7 +39,6 @@ export default new (class {
         })
     }
 
-    // eslint-disable-next-line
     onPlusReady(callback: (plus: any) => void) {
         this.h5.then((res) => {
             callback(res.plus)
@@ -172,7 +172,6 @@ export default new (class {
             })
 
             // 自动更新
-            // eslint-disable-next-line no-inner-declarations
             function installApp(path: string) {
                 plus.nativeUI.showWaiting('正在更新...')
                 plus.runtime.install(
@@ -226,34 +225,40 @@ export default new (class {
     }
 
     /**
-     * 下载文件
+     * 打开本地文件
+     * https://www.html5plus.org/doc/zh_cn/runtime.html#plus.runtime.openFile
      * @param filePath 
      */
-    downloadFile(filePath: string) {
+    openFile(filePath: string) {
         if (this.hasPlus()) {
             this.onPlusReady((plus) => {
-                const getUrl = () => {
-                    try {
-                        const url = new URL(filePath)
-                        return url.href
-                    } catch {
-                        const path = plus.io.convertLocalFileSystemURL('_www/' + filePath)
-                        return 'file://' + path
-                    }
-                }
-                const dtask = plus.downloader.createDownload(getUrl(), {}, (d: unknown, status: number) => {
-                    if (status == 200) {
-                        plus.nativeUI.toast('已保存到文件中')
-                    }
-                    else {
-                        plus.nativeUI.toast('下载失败: ' + status)
-                    }
-                })
-                //dtask.addEventListener('statechanged', onStateChanged, false)
-                dtask.start()
+                plus.runtime.openFile('_www/' + filePath)
             })
         } else {
             window.open(filePath)
         }
     }
+
+    /**
+     * 读取本地文件内容
+     * @param filePath 
+     * @returns 
+     */
+    getLocalFileContent(filePath: string) {
+        return new Promise<any>((resolve, reject) => {
+            this.onPlusReady((plus) => {
+                plus.io.resolveLocalFileSystemURL('_www/' + filePath, (entry: any) => {
+                    entry.file((file: any) => {
+                        const fileReader = new plus.io.FileReader()
+                        fileReader.readAsText(file, 'utf-8')
+                        fileReader.onloadend = (evt: any) => {
+                            resolve(evt.target.result)
+                        }
+                    })
+                }, (e: any) => {
+                    reject(e.message)
+                })
+            })
+        })
+    }
 })