Kaynağa Gözat

init quick app

Zhengxiaowei 5 yıl önce
işleme
553e02a17d
59 değiştirilmiş dosya ile 8721 ekleme ve 0 silme
  1. 65 0
      .eslintrc.json
  2. 12 0
      .gitignore
  3. 8 0
      babel.config.js
  4. 26 0
      package.json
  5. 20 0
      sign/debug/certificate.pem
  6. 28 0
      sign/debug/private.pem
  7. 12 0
      src/api/config.js
  8. 26 0
      src/api/fly.js
  9. 11 0
      src/api/index.js
  10. 34 0
      src/app.ux
  11. BIN
      src/assets/imgs/arrow-right.png
  12. BIN
      src/assets/imgs/binding.png
  13. BIN
      src/assets/imgs/book-vip.png
  14. BIN
      src/assets/imgs/category.png
  15. BIN
      src/assets/imgs/category_choose.png
  16. BIN
      src/assets/imgs/consume_record.png
  17. BIN
      src/assets/imgs/customer.png
  18. BIN
      src/assets/imgs/home.png
  19. BIN
      src/assets/imgs/home_choose.png
  20. BIN
      src/assets/imgs/jinri.png
  21. BIN
      src/assets/imgs/logo.png
  22. BIN
      src/assets/imgs/my.png
  23. BIN
      src/assets/imgs/my_choose.png
  24. BIN
      src/assets/imgs/recharge_record.png
  25. BIN
      src/assets/imgs/shelf.png
  26. BIN
      src/assets/imgs/shelf_choose.png
  27. BIN
      src/assets/imgs/sign.png
  28. BIN
      src/assets/imgs/year_pay.png
  29. 20 0
      src/assets/less/catalog.less
  30. 119 0
      src/assets/less/category.less
  31. 83 0
      src/assets/less/consume.less
  32. 160 0
      src/assets/less/detail.less
  33. 136 0
      src/assets/less/home.less
  34. 66 0
      src/assets/less/index.less
  35. 99 0
      src/assets/less/my.less
  36. 222 0
      src/assets/less/pay.less
  37. 57 0
      src/assets/less/reader.less
  38. 113 0
      src/assets/less/recharge.less
  39. 81 0
      src/assets/less/shelf.less
  40. 119 0
      src/components/book/book.ux
  41. 48 0
      src/components/page/page.ux
  42. 75 0
      src/helper/interface.js
  43. 8 0
      src/helper/regenerator.js
  44. 143 0
      src/manifest.json
  45. 79 0
      src/util.js
  46. 164 0
      src/views/About/index.ux
  47. 34 0
      src/views/Catalog/index.ux
  48. 81 0
      src/views/Category/index.ux
  49. 65 0
      src/views/Consume/index.ux
  50. 102 0
      src/views/Detail/index.ux
  51. 142 0
      src/views/Home/index.ux
  52. 107 0
      src/views/Index/index.ux
  53. 90 0
      src/views/My/index.ux
  54. 187 0
      src/views/Pay/index.ux
  55. 5 0
      src/views/Phone/index.ux
  56. 54 0
      src/views/Reader/index.ux
  57. 68 0
      src/views/Recharge/index.ux
  58. 58 0
      src/views/Shelf/index.ux
  59. 5694 0
      yarn.lock

+ 65 - 0
.eslintrc.json

@@ -0,0 +1,65 @@
+{
+  "env": {
+    "commonjs": true
+  },
+  "extends": "eslint:recommended",
+  "parser": "babel-eslint",
+  "parserOptions": {
+    "sourceType": "module",
+    "ecmaFeatures": {
+      "experimentalObjectRestSpread": true,
+      "jsx": true
+    }
+  },
+  "globals": {
+    "loadData": false,
+    "saveData": false,
+    "history": false,
+    "console": false,
+    "setTimeout": false,
+    "clearTimeout": false,
+    "setInterval": false,
+    "clearInterval": false
+  },
+  "plugins": [
+    "hybrid"
+  ],
+  "rules": {
+    "indent": [
+      "warn",
+      2
+    ],
+    "no-console": [
+      "warn",
+      {
+        "allow": [
+          "info",
+          "warn",
+          "error"
+        ]
+      }
+    ],
+    "no-unused-vars": [
+      "warn",
+      {
+        "varsIgnorePattern": "prompt"
+      }
+    ],
+    "quotes": [
+      "warn",
+      "double",
+      {
+        "avoidEscape": true,
+        "allowTemplateLiterals": true
+      }
+    ],
+    "linebreak-style": [
+      "warn",
+      "unix"
+    ],
+    "semi": [
+      "warn",
+      "always"
+    ]
+  }
+}

+ 12 - 0
.gitignore

@@ -0,0 +1,12 @@
+node_modules
+build
+dist
+
+.DS_Store
+Thumbs.db
+
+*.log
+*.iml
+.idea/
+.vscode/
+.ide/

+ 8 - 0
babel.config.js

@@ -0,0 +1,8 @@
+module.exports = function(api) {
+  api.cache(true)
+  return {
+    presets: ['@babel/preset-env'],
+    plugins: ['@babel/plugin-transform-modules-commonjs'],
+    babelrcRoots: ['.', 'node_modules']
+  }
+}

+ 26 - 0
package.json

@@ -0,0 +1,26 @@
+{
+  "name": "zsy_quick_app",
+  "version": "1.0.0",
+  "subversion": {
+    "toolkit": "0.6.5"
+  },
+  "description": "",
+  "scripts": {
+    "build": "hap build",
+    "release": "hap release",
+    "server": "hap server",
+    "watch": "hap watch"
+  },
+  "devDependencies": {
+    "@types/quickapp": "git+https://github.com/vivoquickapp/quickapp-types.git",
+    "babel-eslint": "^10.0.1",
+    "eslint": "^5.12.1",
+    "eslint-plugin-hybrid": "0.0.5",
+    "hap-toolkit": "^0.6.5",
+    "less": "^3.10.3",
+    "less-loader": "^5.0.0"
+  },
+  "dependencies": {
+    "flyio": "^0.6.14"
+  }
+}

+ 20 - 0
sign/debug/certificate.pem

@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDMTCCAhmgAwIBAgIJAMKpjyszxkDpMA0GCSqGSIb3DQEBCwUAMC4xCzAJBgNV
+BAYTAkNOMQwwCgYDVQQKDANSUEsxETAPBgNVBAMMCFJQS0RlYnVnMCAXDTE3MDQx
+OTAyMzE0OVoYDzIxMTYwMzI2MDIzMTQ5WjAuMQswCQYDVQQGEwJDTjEMMAoGA1UE
+CgwDUlBLMREwDwYDVQQDDAhSUEtEZWJ1ZzCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAK3kPd9jzvTctTIA3XNZVv9cHHDbAc6nTBfdZp9mtPOTkXFpvyCb
+kL0QjOog0+1pv8D7dFeP4ptWXU5CT3ImvaPR+16dAtMRcsxEr5q4zieJzx3O6huL
+UBa1k+xrzjXpRzkcOysmc8fTxt0tAwbDgJ2AA5TlXLTcVyb7GmJ+hl5CjnhoG5NN
+LrkqI7S29c1U3uokj8Q7hzaj0TURu/uB5ZIMCLZY9KFDugqaEcvmUyJiD0fuV6sA
+O/4kpiZUOnhV8/xWpRbMI4WFQsfgLOCV+X9uzUa29D677y//46t/EDSuQTHyBZbl
+AcNMENkpMWZsH7J/+F19+U0/Hd5bJgneVRkCAwEAAaNQME4wHQYDVR0OBBYEFKDN
+SZtt47ttOBDQzIchFYyxsg3mMB8GA1UdIwQYMBaAFKDNSZtt47ttOBDQzIchFYyx
+sg3mMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABaZctNrn4gLmNf/
+eNJ3x5CJIPjPwm6j9nwKhtadJ6BF+TIzSkJuHSgxULjW436F37otv94NPzT5PCBF
+WxgXoqgLqnWwvsaqC4LUEjsZviWW4CB824YDUquEUVGFLE/U5KTZ7Kh1ceyUk4N8
++mtkXkanWoBBk0OF24lNrAsNLB63yTLr9HxEe75+kmvxf1qVJUGtaOEWIhiFMiAB
+5D4w/j2EFWktumjuy5TTwU0zhl52bc8V9SNixM1IaqzNrVPrdjv8viUX548pU3WT
+xZ5ylDsxhMC1q4BXQVeIY8C0cMEX+WHOmOCvWrkxCkP91pKsSPkuVrWlzrkn8Ojo
+swP6sBw=
+-----END CERTIFICATE-----

+ 28 - 0
sign/debug/private.pem

@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCt5D3fY8703LUy
+AN1zWVb/XBxw2wHOp0wX3WafZrTzk5Fxab8gm5C9EIzqINPtab/A+3RXj+KbVl1O
+Qk9yJr2j0ftenQLTEXLMRK+auM4nic8dzuobi1AWtZPsa8416Uc5HDsrJnPH08bd
+LQMGw4CdgAOU5Vy03Fcm+xpifoZeQo54aBuTTS65KiO0tvXNVN7qJI/EO4c2o9E1
+Ebv7geWSDAi2WPShQ7oKmhHL5lMiYg9H7lerADv+JKYmVDp4VfP8VqUWzCOFhULH
+4Czglfl/bs1GtvQ+u+8v/+OrfxA0rkEx8gWW5QHDTBDZKTFmbB+yf/hdfflNPx3e
+WyYJ3lUZAgMBAAECggEBAJTnCBBdUB+fSs1prjeS/gsmnfgJoY+K9H7PCIxgj3yw
+FXAvZAmRDKzJGlF2EOOQlTG0YNiGDj6EAtv7rjoKcINyULSg8IU6wLmn61MrAuUa
+fa+Bujgh4E/B5swhOHAztNhzkzsM70Hi17wXSislh+HWd7qteOgqcbqgdOR4gaj+
+HUqtcxG3H3hCL3dWugnjLZMtestLKGHSSZvbQNjYM3kKy2LvO8NpxmDE4a+TXygK
+qhaZjmS/dc/nJBJzOfkzby58RvGbzlJflfW/Uu3/gizj13GFQKWonq1xh630RAhv
+xX5ySok2aAx/+/SiJSpNXvM09grQuoORSr7D1tm+5rECgYEA3vf0hRfua0XAOu6f
+pyzNvLRRJ/pEew7XpNPCyS2TuMTd1yvXjGVxQfP46N6x1IM3SRU0zE+LSk80EF7l
+u1Or7GyCEhabYNe/7P2F8ENP73Do0HwvcI1jGrgr6r9oK0J27Xei+f6Q0bgJOPI2
+qaLj+V37cOjkNSM1mhTjtDwK8k0CgYEAx6cMrkjHl1+lDIIOc3qAEL3jb3xQveYk
+WrMF/B+j048k6boU4VvFJAIyQxOxMNxLjw3/9+zXCFJT4WaZK3TMXlg614ASGx3H
+tKjJM9O07ywwMq1gbutFS4nHCg3L3Os6esL0SPwMdATR3Yh22n5OGI9o+/aURulL
+GPEXef1Z2/0CgYEAgmwp5LxV4vu+8Pnp+4DSq4ISQr861XyeGTUhKEp3sUm+tgFY
+KTChakHKpHS3Mqa6bQ5xft08je/8dWL9IHFWDIqAHxKIOsKY6oh1k0/cbyPtmx45
+Ja4efV+jmMHzrfJH3KnxdCg7D+GFy4CrBtlYXuJhlO81pft9fC6h7yh8ArUCgYBq
+gvkl5Zftbs4rnRq+iqTVyagTKvwcQzIz3PwdZHfO/rfPpUFMdNv4eN99n3zRN0Vs
+HSjoiEazntA3GLgwUdBRqLpDi4SdSMbo337vkksdqbJQ5uPiaMuAIBG6kF+pDSkW
+ovkWErlGD+gySoI10FozihaVDRhPuFgjB0PiBcIxtQKBgGNSzX+Bx5+ux1Qny0Sn
+SUcBtepLnO8M8wafoGNyehbMnLzfuMbaDiJOdozGlBNHZTtPB3r4AYb8WnltdKW0
+7i3fk26YZGiMVeUJvewA6/LOBEaqMdwoNwnoptvbR6ehHeE/PPtRtge2cD3bPIM7
+U9VlWgfgj9Dxfwhslqb9hmyp
+-----END PRIVATE KEY-----

+ 12 - 0
src/api/config.js

@@ -0,0 +1,12 @@
+/*
+ * @Author: ZhengXiaowei
+ * @Date: 2019-10-15 12:06:24
+ * @LastEditors: ZhengXiaowei
+ * @LastEditTime: 2019-10-15 14:11:17
+ * @Description: api配置文件
+ */
+const apiConfig = {
+  baseURL: "http://m.pre.ycsd.cn/api"
+};
+
+export default apiConfig;

+ 26 - 0
src/api/fly.js

@@ -0,0 +1,26 @@
+/*
+ * @Author: ZhengXiaowei
+ * @Date: 2019-10-15 12:06:28
+ * @LastEditors: ZhengXiaowei
+ * @LastEditTime: 2019-10-15 14:32:19
+ * @Description: api 配置入口
+ */
+import fetch from "@system.fetch";
+import Fly from "flyio/dist/npm/hap";
+import apiConfig from "./config";
+
+var fly = new Fly(fetch);
+
+fly.config.baseURL = apiConfig.baseURL;
+
+fly.interceptors.response.use(
+  res => {
+    if (res.data.code === 0) return res.data.data;
+    return Promise.reject(res.data);
+  },
+  err => {
+    return Promise.reject(err);
+  }
+);
+
+export default fly;

+ 11 - 0
src/api/index.js

@@ -0,0 +1,11 @@
+/*
+ * @Author: ZhengXiaowei
+ * @Date: 2019-10-15 14:05:33
+ * @LastEditors: ZhengXiaowei
+ * @LastEditTime: 2019-10-15 14:05:59
+ * @Description: api
+ */
+import fly from "./fly";
+export const demoApi = () => {
+  return fly.get("/home/index");
+};

+ 34 - 0
src/app.ux

@@ -0,0 +1,34 @@
+<!--
+ * @Author: ZhengXiaowei
+ * @Date: 2019-10-15 12:02:18
+ * @LastEditors: ZhengXiaowei
+ * @LastEditTime: 2019-10-15 14:02:07
+ * @Description: 主入口
+ -->
+<script>
+/**
+ * 应用级别的配置,供所有页面公用
+ */
+import "./helper/regenerator.js";
+import it from "./helper/interface.js";
+
+export default {
+  onCreate() {
+    // 一进入程序就判断是否添加过主屏幕
+    it.shortcut.systemPromptEnabled = false;
+    it.shortcut.hasInstalled({
+      success: (ret) => {
+        if (!ret) this.$def.data.backClickCount = 0;
+        else this.$def.data.backClickCount = 1;
+      }
+    })
+  },
+  showMenu: it.showMenu,
+  getDeviceInfo: it.getDeviceInfo,
+  createShortcut: it.hasCreateShortCut,
+  data: {
+    backClickCount: 0,
+    cutomerQrcode: "https://cdn-novel.iycdm.com/static/img/kefu.jpg"
+  }
+};
+</script>

BIN
src/assets/imgs/arrow-right.png


BIN
src/assets/imgs/binding.png


BIN
src/assets/imgs/book-vip.png


BIN
src/assets/imgs/category.png


BIN
src/assets/imgs/category_choose.png


BIN
src/assets/imgs/consume_record.png


BIN
src/assets/imgs/customer.png


BIN
src/assets/imgs/home.png


BIN
src/assets/imgs/home_choose.png


BIN
src/assets/imgs/jinri.png


BIN
src/assets/imgs/logo.png


BIN
src/assets/imgs/my.png


BIN
src/assets/imgs/my_choose.png


BIN
src/assets/imgs/recharge_record.png


BIN
src/assets/imgs/shelf.png


BIN
src/assets/imgs/shelf_choose.png


BIN
src/assets/imgs/sign.png


BIN
src/assets/imgs/year_pay.png


+ 20 - 0
src/assets/less/catalog.less

@@ -0,0 +1,20 @@
+.catalog-wrap {
+  padding: 0 24px;
+
+  .catalog-item {
+    height: 90px;
+    justify-content: space-between;
+    align-items: center;
+
+    .catalog-name {
+      color: #4c4c4c;
+      font-size: 28px;
+      lines: 1;
+      text-overflow: ellipsis;
+    }
+
+    image {
+      width: 30px;
+    }
+  }
+}

+ 119 - 0
src/assets/less/category.less

@@ -0,0 +1,119 @@
+.category-wrap {
+  background-color: #f7f7f7;
+  flex-direction: column;
+
+  .search-bar {
+    padding: 24px;
+
+    .search-bar__wrap {
+      flex: 1;
+      background-color: #fff;
+      height: 62px;
+      padding: 0 14px;
+      border-radius: 30px;
+      align-items: center;
+
+      image {
+        margin-right: 20px;
+        width: 36px;
+        height: 36px;
+      }
+
+      input {
+        flex: 1;
+        font-size: 24px;
+        color: #999;
+      }
+    }
+  }
+
+  .filter-wrap {
+    background-color: #fff;
+    flex-direction: column;
+    margin-bottom: 24px;
+
+    .filter-item {
+      flex: 1;
+      align-items: flex-start;
+      padding: 32px 42px 0;
+      border-bottom: 2px solid #f7f7f7;
+      
+      
+      &__list {
+        flex: 1;
+        flex-direction: row;
+        flex-wrap: wrap;
+
+        text {
+          width: 25%;
+          flex-shrink: 0;
+          text-align: center;
+          padding-bottom: 32px;
+        }
+      }
+
+      &__name {
+        width: 20%;
+        flex-shrink: 0;
+        font-size: 26px;
+        color: #333;
+      }
+
+      &__item {
+        font-size: 26px;
+        color: #333;
+      }
+
+      & .cur {
+        font-weight: bold;
+        color: #3284ff;
+      }
+    }
+  }
+
+  .books-item__wrap {
+    background-color: #fff;
+    padding: 24px;
+    flex-direction: column;
+
+    .book-info {
+      flex: 1;
+      flex-direction: column;
+      justify-content: space-between;
+      padding-left: 40px;
+
+      .name {
+        color: #333;
+        font-size: 30px;
+        lines: 1;
+        text-overflow: ellipsis;
+      }
+      
+      .status,
+      .words {
+        color: #999;
+        font-size: 26px;
+      }
+
+      .update {
+        align-items: center;
+
+        text {
+          font-size: 26px;
+          color: #ff6060;
+        }
+
+        .lastest {
+          color: #666;
+        }
+
+        image {
+          width: 30px;
+          height: 30px;
+          margin-left: 10px;
+        }
+      }
+
+    }
+  }
+}

+ 83 - 0
src/assets/less/consume.less

@@ -0,0 +1,83 @@
+.consume-record__wrap {
+  flex-direction: column;
+
+  .tabbar-wrap {
+    height: 80px;
+    justify-content: space-between;
+    align-items: center;
+
+    text {
+      color: #333;
+      font-size: 30px;
+    }
+
+    .tab-item {
+      flex: 1;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+
+      .tab-active__border {
+        height: 6px;
+        width: 60px;
+        border-radius: 4px;
+        background-color: #fff;
+        margin-top: 10px;
+
+        &--active {
+          background-color: #3284ff;
+        }
+      }
+      
+      .active {
+        color: #3284ff;
+      }
+    }
+  }
+
+  .consume-wrap {
+    flex-direction: column;
+
+    .consume-item {
+      justify-content: space-between;
+      align-items: center;
+      margin: 24px 24px 0;
+      padding-bottom: 24px;
+      border-bottom: 2px solid #f7f7f7;
+
+      .consume-info {
+        flex: 1;
+        flex-direction: column;
+        justify-content: flex-start;
+        align-items: flex-start;
+        margin-right: 40px;
+
+        .name {
+          font-size: 30px;
+          color: #333;
+          lines: 1;
+          text-overflow: ellipsis;
+        }
+
+        .chapter {
+          font-size: 26px;
+          color: #333;
+          margin-top: 18px;
+          lines: 1;
+          text-overflow: ellipsis;
+        }
+
+        .create {
+          font-size: 24px;
+          color: #999;
+          margin-top: 18px;
+        }
+      }
+
+      .consume-price {
+        color: #ff6060;
+        font-size: 26px;
+      }
+    }
+  }
+}

+ 160 - 0
src/assets/less/detail.less

@@ -0,0 +1,160 @@
+.detail-wrap {
+  flex-direction: column;
+
+  .book-wrap {
+    padding: 24px;
+    flex-direction: column;
+  }
+
+  .book-info {
+    margin-left: 40px;
+    flex-direction: column;
+    justify-content: space-between;
+    align-items: flex-start;
+
+    .name {
+      lines: 1;
+      text-overflow: ellipsis;
+      font-size: 30px;
+      color: #333;
+    }
+
+    .category {
+      text {
+        color: #999;
+        font-size: 24px;
+      }
+
+      .status {
+        color: #ff6060;
+        margin-left: 120px;
+      }
+    }
+
+    .words {
+      font-size: 24px;
+      color: #999;
+    }
+
+    .user-operator {
+      text {
+        width: 180px;
+        height: 55px;
+        text-align: center;
+        border: 2px solid #ff6060;
+        border-radius: 6px;
+        color: #ff6060;
+        font-size: 24px;
+      }
+
+      .read {
+        margin-left: 40px;
+        color: #fff;
+        background-color: #ff6060;
+      }
+    }
+  }
+
+  .book-intro {
+    margin-top: 24px;
+    flex-direction: column;
+
+    text {
+      font-size: 26px;
+      color: #666;
+    }
+
+    .short-info__text {
+      line-height: 45px;
+
+      .toggle {
+        color: #3284ff;
+      }
+    }
+
+    .toggle {
+      color: #3284ff;
+      align-self: center;
+    }
+  }
+
+  .lastest-chapter {
+    lines: 1;
+    text-overflow: ellipsis;
+    padding: 0 24px;
+    font-size: 26px;
+    height: 90px;
+    color: #3284ff;
+    background-color: #f7f7f7;
+  }
+
+  .box-wrap {
+    flex-direction: column;
+
+    .small-title {
+      justify-content: space-between;
+      align-items: center;
+      padding: 0 24px;
+      margin: 24px 0;
+
+      text {
+        font-size: 24px;
+        color: #999;
+      }
+
+      .wrap-left {
+        align-items: center;
+      }
+
+      .wrap-right {
+        align-self: flex-end;
+      }
+
+      .title {
+        font-size: 28px;
+        color: #3284ff;
+        margin-right: 10px;
+      }
+
+      .total {
+        align-self: flex-end;
+      }
+
+      .border-left {
+        width: 4px;
+        height: 28px;
+        background-color: #3284ff;
+        border-radius: 4px;
+        margin-right: 20px;
+      }
+    }
+  }
+
+  .chapter-list {
+    flex-direction: column;
+    padding: 0 24px;
+
+    .chapter-item {
+      color: #4c4c4c;
+      font-size: 28px;
+      height: 90px;
+      lines: 1;
+      text-overflow: ellipsis;
+    }
+  }
+
+  .more-chapters {
+    text-align: center;
+    background-color: #f7f7f7;
+    color: #3284ff;
+    font-size: 26px;
+    height: 90px;
+    padding: 0 24px;
+  }
+
+  .similar-wrap {
+    padding: 0 24px;
+    justify-content: space-between;
+    align-items: flex-start;
+  }
+}

+ 136 - 0
src/assets/less/home.less

@@ -0,0 +1,136 @@
+.home-wrap {
+  background-color: #f7f7f7;
+  flex-direction: column;
+
+  .type-bar {
+    background-color: #3284ff;
+
+    .type-item {
+      flex: 1;
+      justify-content: center;
+      align-items: center;
+      flex-direction: column;
+
+      text {
+        font-size: 30px;
+        color: #BBE0FF;
+        padding: 34px 0;
+      }
+
+      .cur {
+        color: #fff;
+        font-size: 32px;
+        font-weight: bold;
+      }
+
+      image {
+        width: 52px;
+        height: 18px;
+      }
+    }
+  }
+  
+  .search-bar {
+    padding: 24px;
+
+    .search-bar__wrap {
+      flex: 1;
+      background-color: #fff;
+      height: 62px;
+      padding: 0 14px;
+      border-radius: 30px;
+      align-items: center;
+
+      image {
+        margin-right: 20px;
+        width: 36px;
+        height: 36px;
+      }
+
+      text {
+        flex: 1;
+        font-size: 24px;
+        color: #999;
+      }
+    }
+  }
+
+  .swipe-bar {
+    height: 350px;
+    background-color: #fff;
+
+    .swipe-item {
+      padding: 30px 24px;
+
+      .swipe-item__info {
+        flex: 1;
+        flex-direction: column;
+        padding-right: 32px;
+
+        .name {
+          font-size: 32px;
+          color: #333;
+        }
+
+        .intro {
+          font-size: 26px;
+          color: #666;
+          margin-top: 36px;
+          lines: 4;
+          text-overflow: ellipsis;
+        }
+
+        .category {
+          font-size: 24px;
+          color: #32a1ff;
+          margin-top: 10px;
+        }
+      }
+
+      .cover {
+        flex-basis: 180px;
+        flex-shrink: 0;
+        height: 240px;
+        border-radius: 6px;
+      }
+    }
+  }
+
+  .book-list__wrap {
+    background-color: #fff;
+    margin-top: 24px;
+    padding: 0 24px;
+    flex-direction: column;
+
+    .book-list__title {
+      padding: 38px 0;
+      align-items: center;
+      
+      span {
+        width: 6px;
+        height: 34px;
+        background-color: #32a1ff;
+      }
+
+      text {
+        color: #32a1ff;
+        font-size: 30px;
+      }
+
+      .border {
+        background-color: #32a1ff;
+        width: 6px;
+        height: 100%;
+        border-radius: 2px;
+        margin-right: 20px;
+      }
+    }
+  }
+
+  .book-list {
+    flex: 1;
+    flex-direction: row;
+    flex-wrap: wrap;
+    justify-content: space-between;
+  }
+}

+ 66 - 0
src/assets/less/index.less

@@ -0,0 +1,66 @@
+.index-wrap {
+  flex-direction: column;
+
+  .fixed-tabbar {
+    height: 120px;
+    flex-shrink: 0;
+    background-color: #fff;
+    border-top: 2px solid #bfbfbf;
+
+    .tabbar-item {
+      flex: 1;
+      flex-direction: column;
+      justify-content: center;
+      align-items: center;
+
+      image {
+        width: 46px;
+        height: 46px;
+      }
+
+      text {
+        color: #999;
+        font-size: 24px;
+      }
+
+      .tabbar-name__cur {
+        color: #3284ff;
+      }
+    }
+  }
+
+  .tab-content {
+    flex: 1;
+  }
+}
+
+.stack-popup {
+  background-color: rgba(0, 0, 0, .6);
+  width: 100%;
+  height: 100%;
+  justify-content: center;
+  align-items: center;
+
+  .customer-popup {
+    width: 610px;
+    border-radius: 6px;
+    background-color: #fff;
+    flex-direction: column;
+    align-items: center;
+
+    .title {
+      width: 100%;
+      font-size: 36px;
+      text-align: center;
+      color: #333;
+      padding: 30px 0;
+      border-bottom: 2px solid #f7f7f7;
+    }
+
+    image {
+      margin: 20px 0;
+      width: 400px;
+      height: 400px;
+    }
+  }
+}

+ 99 - 0
src/assets/less/my.less

@@ -0,0 +1,99 @@
+.user-wrap {
+  flex-direction: column;
+
+  .user-info__wrap {
+    background-color: #3284ff;
+    padding: 40px;
+
+    image {
+      width: 160px;
+      height: 160px;
+      border-radius: 100px;
+      margin-right: 40px;
+    }
+
+    text {
+      color: #fff;
+      font-size: 32px;
+    }
+  }
+
+  .user-coin__wrap {
+    background-color: #3284ff;
+    justify-content: space-between;
+    align-items: center;
+    padding: 40px 120px;
+    
+    .user-rest {
+      flex-direction: row;
+      justify-content: flex-start;
+      align-items: center;
+      
+      text {
+        color: #fff;
+        font-size: 32px;
+      }
+
+      .rest-coin {
+        color: #ff6060;
+        font-weight: bold;
+      }
+    }
+
+    .pay-btn {
+      background-color: #ff6060;
+      color: #fff;
+      width: 100px;
+      height: 48px;
+      line-height: 48px;
+      text-align: center;
+      border-radius: 6px;
+    }
+  }
+
+  .operator-item__wrap {
+    flex-direction: column;
+    border-top: 24px solid #f7f7f7;
+    
+    .operator-item {
+      padding: 34px 26px;
+      border-bottom: 2px solid #f7f7f7;
+      justify-content: space-between;
+      align-items: center;
+
+      .item-name {
+        flex: 1;
+
+        image {
+          width: 40px;
+          margin-right: 40px;
+        }
+
+        text {
+          font-size: 30px;
+          color: #545454;
+        }
+      }
+
+      .info-text {
+        align-items: center;
+
+        text {
+          font-size: 24px;
+          color: #999;
+          margin-right: 20px;
+        }
+
+        .arrow {
+          width: 12px;
+        }
+      }
+    }
+  }
+
+  .customer-dialog {
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, .4);
+  }
+}

+ 222 - 0
src/assets/less/pay.less

@@ -0,0 +1,222 @@
+.pay-wrap {
+  flex-direction: column;
+
+  .wrap-relative {
+    flex: 1;
+    flex-direction: column;
+  }
+
+  .wrap-fixed {
+    height: 120px;
+    flex-shrink: 0;
+    background-color: #fff;
+    border-top: 2px solid #f7f7f7;
+    background-color: #fff;
+    justify-content: space-between;
+    align-items: center;
+    padding: 28px 24px;
+
+    .total-cost {
+      flex: 1;
+      flex-direction: column;
+
+      text {
+        font-size: 30px;
+        color: #666;
+        font-weight: bold;
+      }
+
+      .notice {
+        font-size: 24px;
+        color: #999;
+        font-weight: normal;
+      }
+    }
+
+    .go-to-pay {
+      font-size: 30px;
+      font-weight: bold;
+      color: #fff;
+      border-radius: 6px;
+      background-color: #ff6060;
+      padding: 20px 40px;
+    }
+  }
+
+  .top-user__wrap {
+    flex-direction: column;
+    padding: 0 24px 20px;
+    margin: 24px 0;
+    border-bottom: 20px solid #f7f7f7;
+
+    .user-balance {
+      margin-bottom: 10px;
+
+      text {
+        font-size: 30px;
+        color: #333;
+      }
+
+      .balance {
+        color: #ff6060;
+        font-weight: bold;
+      }
+    }
+
+    .chapter-cost {
+      text {
+        font-size: 24px;
+        color: #666;
+      }
+
+      .cost {
+        color: #ff6060;
+        font-weight: bold;
+        margin: 0 10px;
+      }
+    }
+  }
+
+  .charge-wrap {
+    padding: 0 24px;
+    flex-direction: column;
+
+    .title {
+      align-items: center;
+
+      text {
+        font-size: 30px;
+        color: #333;
+      }
+
+      .border {
+        width: 4px;
+        height: 30px;
+        border-radius: 4px;
+        background-color: #ff6060;
+        margin-right: 10px;
+      }
+    }
+
+    .pay-type {
+      justify-content: space-between;
+      align-items: center;
+      margin-top: 30px;
+
+      &__item {
+        width: 48%;
+        height: 100px;
+        justify-content: center;
+        align-items: center;
+        border: 2px solid #f7f7f7;
+        border-radius: 6px;
+        background-color: #f7f7f7;
+
+        image {
+          width: 70px;
+          margin-right: 40px;
+        }
+
+        text {
+          font-size: 30px;
+          color: #666;
+        }
+      }
+
+      &__item--cur {
+        background-color: #fff;
+        border-color: #ff393a;
+      }
+    }
+
+    .recharge-list {
+      margin-top: 30px;
+      flex-direction: row;
+      flex-wrap: wrap;
+      justify-content: space-between;
+      align-items: center;
+
+      .recharge-item {
+        flex-direction: column;
+        justify-content: center;
+        align-items: center;
+        width: 340px;
+        height: 180px;
+        background-color: #f7f7f7;
+        border-radius: 6px;
+        border: 2px solid #f7f7f7;
+
+        .price {
+          font-size: 36px;
+          color: #666;
+          font-weight: bold;
+
+          &__select {
+            color: #ff393a;
+          }
+        }
+
+        .send {
+          font-size: 26px;
+          color: #999;
+          margin-bottom: 10px;
+
+          &__select {
+            color: #ff393a;
+          }
+        }
+
+        .discount {
+          border: 2px solid #ff9470;
+          border-radius: 50px;
+          background-color: #ff9470;
+          overflow: hidden;
+
+          image {
+            width: 32px;
+            height: 32px;
+            margin: 0 10px;
+          }
+
+          text {
+            font-size: 24px;
+            color: #fff;
+            padding: 0 10px;
+          }
+          
+          .discount-num {
+            color: #ff9470;
+            background-color: #fff;
+            border-radius: 50px;
+
+            &__select {
+              color: #ff393a;
+            }
+          }
+
+          &__select {
+            border-color: #ff393a;
+            background-color: #ff393a;
+
+          }
+        }
+
+        &__select {
+          background-color: #fff5f6;
+          border-color: #ff393a;
+        }
+      }
+    }
+  }
+
+  .stack-wrap {
+    margin-bottom: 30px;
+
+    .recharge-recommend {
+      width: 120px;
+      height: 50px;
+      position: absolute;
+      right: 0;
+    }
+  }
+}

+ 57 - 0
src/assets/less/reader.less

@@ -0,0 +1,57 @@
+.reader-wrap {
+  flex-direction: column;
+  background-color: #e6e6e6;
+  
+  .reader-title {
+    margin: 0 24px;
+    padding: 40px 0;
+    border-bottom: 2px solid #ccc;
+    justify-content: space-between;
+    align-items: center;
+
+    text {
+      color: #1a1a1a;
+    }
+
+    .title {
+      font-size: 38px;
+    }
+
+    .add-shelf {
+      font-size: 26px;
+      width: 144px;
+      height: 42px;
+      text-align: center;
+      border-radius: 100px;
+      background-color: #d9d9d9;
+    }
+  }
+
+  .reader-content {
+    margin: 0 24px;
+    flex-direction: column;
+
+    .chapter-text {
+      text-indent: 2em;
+      font-size: 32px;
+      margin-top: 30px;
+      line-height: 60px;
+    }
+  }
+
+  .reader-operator {
+    margin: 50px 24px 40px;
+    justify-content: space-between;
+    align-items: center;
+
+    text {
+      width: 214px;
+      height: 80px;
+      color: #1a1a1a;
+      background-color: #e6e6e6;
+      border: 2px solid #666;
+      border-radius: 6px;
+      text-align: center;
+    }
+  }
+}

+ 113 - 0
src/assets/less/recharge.less

@@ -0,0 +1,113 @@
+.recharge-record__wrap {
+  flex-direction: column;
+
+  .user-account__wrap {
+    flex-direction: column;
+    border-bottom: 12px solid #f7f7f7;
+
+    .title-bar {
+      margin: 35px 0;
+      align-items: center;
+
+      .title {
+        font-size: 28px;
+        color: #3284ff;
+      }
+
+      .border-bar {
+        width: 6px;
+        height: 100%;
+        background-color: #3284ff;
+        border-radius: 4px;
+        margin-right: 20px;
+      }
+    }
+
+    .balance-bar {
+      justify-content: space-between;
+      align-items: center;
+      padding: 0 40px;
+      margin-bottom: 34px;
+
+      .balance {
+        text {
+          font-size: 24px;
+          color: #333;
+        }
+
+        .balance-number {
+          color: #ff6060;
+          font-weight: bold;
+          font-size: 32px;
+        }
+      }
+
+      .pay-btn {
+        background-color: #ff6060;
+        color: #fff;
+        font-size: 26px;
+        text-align: center;
+        width: 180px;
+        height: 60px;
+        line-height: 60px;
+        border-radius: 6px;
+      }
+    }
+  }
+
+  .recharge-list__wrap {
+    border-bottom: 0;
+  }
+
+  .recharge-list {
+    flex-direction: column;
+
+    .recharge-item {
+      justify-content: space-between;
+      align-items: center;
+      margin: 24px 24px 0;
+      border-bottom: 2px solid #f7f7f7;
+
+      .item-info {
+        flex: 1;
+        flex-direction: column;
+        justify-content: flex-start;
+        align-items: flex-start;
+
+        .item-name,
+        .item-number {
+          font-size: 24px;
+          color: #999;
+        }
+
+        .item-number {
+          margin: 10px 0;
+        }
+
+        .item-pay {
+          padding-bottom: 20px;
+
+          text {
+            font-size: 24px;
+            color: #333;
+          }
+
+          .pay-number {
+            font-size: 36px;
+            font-weight: bold;
+            color: #ff6060;
+          }
+        }
+      }
+
+      .item-status {
+        font-size: 24px;
+        color: #ff6060;
+      }
+
+      .paid {
+        color: greenyellow;
+      }
+    }
+  }
+}

+ 81 - 0
src/assets/less/shelf.less

@@ -0,0 +1,81 @@
+.shelf-wrap {
+  // border-top: 36px solid #f7f7f7;
+  flex-direction: column;
+
+  .border-bar {
+    height: 36px;
+    background-color: #f7f7f7;
+  }
+  
+  .shelf-total {
+    padding: 32px 22px;
+    justify-content: space-between;
+    align-items: center;
+
+    text {
+      color: #333;
+      font-size: 26px;
+    }
+
+    .manager {
+      border: 2px solid #3284ff;
+      border-radius: 6px;
+      background-color: #fff;
+      font-size: 26px;
+      color: #3284ff;
+      width: 88px;
+      height: 38px;
+      text-align: center;
+    }
+  }
+
+  .shelf-books__wrap {
+    padding: 0 22px;
+    justify-content: flex-start;
+    flex-direction: row;
+    flex-wrap: wrap;
+
+    .book-item__wrap {
+      margin-right: 50px;
+
+      .book-del__wrap {
+        background-color: rgba(255, 255, 255, .6);;
+        width: 200px;
+        height: 264px;
+        border-radius: 6px;
+        justify-content: center;
+        align-items: center;
+        flex-direction: column;
+
+        image {
+          width: 40px;
+        }
+
+        text {
+          color: #4d4d4d;
+          margin-top: 20px;
+        }
+      }
+    }
+
+    .book-item__add {
+      flex-direction: column;
+
+      .add-cover {
+        width: 200px;
+      }
+
+      text {
+        font-size: 24px;
+        text-align: center;
+        color: #999;
+        margin-top: 14px;
+      }
+    }
+
+    & .m0 {
+      margin-right: 0;
+    }
+
+  }
+}

+ 119 - 0
src/components/book/book.ux

@@ -0,0 +1,119 @@
+<template>
+  <div class="{{multi ? 'book-wrap__multi' : 'book-wrap'}}" @click="getBooks(book)">
+    <block if="!multi">
+      <image class="book-cover__simple" src="https://cdn-newyc.ycsd.cn/ycsd_cover/covermiddle/11/11989.jpg?t=2019101714"></image>
+      <text class="book-name">惊世妖娆凤凰月惊世妖娆凤凰月</text>
+    </block>
+    <block else>
+      <image class="book-cover__multi" src="https://cdn-newyc.ycsd.cn/ycsd_cover/covermiddle/11/11989.jpg?t=2019101714"></image>
+      <slot>
+        <div class="book-info__multi">
+          <text class="name">惊世妖娆凤凰月惊世妖娆凤凰月</text>
+          <text class="intro">我作为一名公司普通的小职员,一觉醒来居然被人睡了,本来以为只是一次简单的意外事件,却不料因此被人蓄意利用卷卷卷进,我作为一名公司普通的小职员,一觉醒来居然被人睡了,本来以为只是一次简单的意外事件,却不料因此被人蓄意利用卷卷卷进...</text>
+        </div>
+      </slot>
+    </block>
+  </div>
+</template>
+
+<script>
+import router from "@system.router";
+
+export default {
+  props: {
+    multi: {
+      type: Boolean,
+      default: false
+    },
+    prevent: {
+      type: Boolean,
+      default: false
+    },
+    similar: {
+      type: Boolean,
+      default: false
+    },
+    book: {
+      type: Object,
+      default: {}
+    }
+  },
+  getBooks(book) {
+    if (this.prevent) return;
+    if (this.similar) {
+      router.replace({
+        uri: "/views/Detail",
+        params: {
+          bid: book.bid || ""
+        }
+      })
+    } else {
+      router.push({
+        uri: "/views/Detail",
+        params: {
+          bid: book.bid || ""
+        }
+      })
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.book-wrap {
+  width: 200px;
+  flex-shrink: 0;
+  flex-direction: column;
+
+  .book-cover__simple {
+    width: 100%;
+    height: 264px;
+    border-radius: 6px;
+  }
+
+  .book-name {
+    font-size: 24px;
+    color: #999;
+    margin-top: 14px;
+    margin-bottom: 36px;
+    lines: 1;
+    text-overflow: ellipsis;
+  }
+}
+
+.book-wrap__multi {
+  /* flex: 1; */
+  flex-direction: row;
+
+  .book-cover__multi {
+    width: 200px;
+    flex-shrink: 0;
+    height: 266px;
+    border-radius: 6px;
+  }
+
+  .book-info__multi {
+    flex: 1;
+    height: 266px;
+    flex-direction: column;
+    margin-left: 38px;
+    margin-bottom: 40px;
+
+    .name {
+      font-size: 36px;
+      color: #333;
+      margin-bottom: 54px;
+      lines: 1;
+      text-overflow: ellipsis;
+    }
+
+    .intro {
+      font-size: 26px;
+      color: #666;
+      line-height: 40px;
+      lines: 4;
+      text-overflow: ellipsis;
+    }
+  }
+}
+</style>

+ 48 - 0
src/components/page/page.ux

@@ -0,0 +1,48 @@
+<template>
+  <div class="page-wrap">
+    <text class="btn prev" @click="prev">上一页</text>
+    <text class="btn">{{current + '/' + total}}</text>
+    <text class="btn next" @click="next">下一页</text>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    current: {
+      type: Number,
+      default: 1
+    },
+    total: {
+      type: Number,
+      default: 1
+    }
+  },
+  prev() {
+    if (this.current === 1) return;
+    this.$emit("prev");
+  },
+  next() {
+    if (this.current === this.total) return;
+    this.$emit("next");
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.page-wrap {
+  margin: 40px 30px;
+  justify-content: space-between;
+  align-items: center;
+
+  text {
+    width: 165px;
+    height: 55px;
+    background-color: #f7f7f7;
+    color: #3284ff;
+    font-size: 30px;
+    text-align: center;
+    border-radius: 6px;
+  }
+}
+</style>

+ 75 - 0
src/helper/interface.js

@@ -0,0 +1,75 @@
+import app from "@system.app";
+import device from "@system.device";
+import prompt from "@system.prompt";
+import shortcut from "@system.shortcut";
+import router from "@system.router";
+
+const SHORT_CUT_FORBIDDEN_INFO = "User forbidden";
+
+// 获取设备信息
+const getDeviceInfo = () => {
+  device.getDeviceId({
+    success: (ret) => {
+      console.log(ret)
+    }
+  })
+}
+
+// 判断用户是否创建图标
+const hasCreateShortCut = (isPayPage = false) => {
+  shortcut.hasInstalled({
+    success: (ret) => {
+      if (!ret) {
+        shortcut.install({
+          message: "添加【追书云】到桌面,方便下次阅读",
+          success: () => {
+            prompt.showToast("添加成功!");
+          },
+          fail: (code) => {
+            if (code === SHORT_CUT_FORBIDDEN_INFO && !isPayPage) app.exit();
+          }
+        })
+      }
+    }
+  })
+}
+
+// 右上角菜单点击
+const showMenu = () => {
+  const appInfo = app.getInfo();
+  prompt.showContextMenu({
+    itemList: ["保存桌面", "关于", "取消"],
+    success: function (ret) {
+      switch (ret.index) {
+        case 0:
+          // 保存桌面
+          hasCreateShortCut();
+          break;
+        case 1:
+          // 关于
+          router.push({
+            uri: "/views/About",
+            params: {
+              name: appInfo.name,
+              icon: appInfo.icon
+            }
+          });
+          break;
+        case 2:
+          // 取消
+          break;
+        default:
+          prompt.showToast({
+            message: "错误"
+          });
+      }
+    }
+  });
+}
+
+export default {
+  shortcut,
+  getDeviceInfo,
+  hasCreateShortCut,
+  showMenu
+}

+ 8 - 0
src/helper/regenerator.js

@@ -0,0 +1,8 @@
+// 脚本:regenerator.js
+// 注意:仅用于注入类库函数,不允许存储页面组件等数据
+const injectRef = Object.getPrototypeOf(global) || global
+
+// 注入regeneratorRuntime
+injectRef.regeneratorRuntime = require('@babel/runtime/regenerator')
+// 如果使用的 hap-toolkit 版本低于0.0.38(babel 版本低于 7),则按下面的方式引入
+// injectRef.regeneratorRuntime = require('babel-runtime/regenerator')

+ 143 - 0
src/manifest.json

@@ -0,0 +1,143 @@
+{
+  "package": "com.application.demo",
+  "name": "追书云小说",
+  "versionName": "1.0.0",
+  "versionCode": "1",
+  "minPlatformVersion": "1020",
+  "icon": "/assets/imgs/logo.png",
+  "features": [
+    {
+      "name": "system.app"
+    },
+    {
+      "name": "system.prompt"
+    },
+    {
+      "name": "system.router"
+    },
+    {
+      "name": "system.shortcut"
+    },
+    {
+      "name": "system.fetch"
+    },
+    {
+      "name": "system.device"
+    },
+    {
+      "name": "system.storage"
+    }
+  ],
+  "permissions": [
+    {
+      "origin": "*"
+    }
+  ],
+  "config": {
+    "logLevel": "debug"
+  },
+  "router": {
+    "entry": "views/Index",
+    "pages": {
+      "views/Index": {
+        "component": "index"
+      },
+      "views/Home": {
+        "component": "index"
+      },
+      "views/Category": {
+        "component": "index"
+      },
+      "views/Shelf": {
+        "component": "index"
+      },
+      "views/My": {
+        "component": "index"
+      },
+      "views/Reader": {
+        "component": "index"
+      },
+      "views/Catalog": {
+        "component": "index"
+      },
+      "views/Detail": {
+        "component": "index"
+      },
+      "views/About": {
+        "component": "index"
+      },
+      "views/Recharge": {
+        "component": "index"
+      },
+      "views/Consume": {
+        "component": "index"
+      },
+      "views/Phone": {
+        "component": "index"
+      },
+      "views/Pay": {
+        "component": "index"
+      }
+    },
+    "widgets": {}
+  },
+  "display": {
+    "titleBarBackgroundColor": "#3284ff",
+    "titleBarTextColor": "#fff",
+    "menu": true,
+    "pages": {
+      "views/Index": {
+        "titleBarText": "追书云",
+        "menu": true
+      },
+      "views/Home": {
+        "titleBarText": "追书云",
+        "menu": false
+      },
+      "views/Category": {
+        "titleBarText": "分类",
+        "menu": false
+      },
+      "views/Shelf": {
+        "titleBarText": "我的书架",
+        "menu": false
+      },
+      "views/My": {
+        "titleBarText": "个人中心",
+        "menu": false
+      },
+      "views/About": {
+        "titleBarText": "关于追书云",
+        "menu": false
+      },
+      "views/Recharge": {
+        "titleBarText": "充值记录",
+        "menu": false
+      },
+      "views/Consume": {
+        "titleBarText": "消费记录",
+        "menu": false
+      },
+      "views/Phone": {
+        "titleBarText": "绑定手机",
+        "menu": false
+      },
+      "views/Pay": {
+        "titleBarText": "充值",
+        "menu": false
+      },
+      "views/Reader": {
+        "titleBarText": "阅读器",
+        "menu": false
+      },
+      "views/Catalog": {
+        "titleBarText": "目录",
+        "menu": false
+      },
+      "views/Detail": {
+        "titleBarText": "详情页",
+        "menu": false
+      }
+    }
+  }
+}

+ 79 - 0
src/util.js

@@ -0,0 +1,79 @@
+/*
+ * @Author: ZhengXiaowei
+ * @Date: 2019-10-15 12:02:18
+ * @LastEditors: ZhengXiaowei
+ * @LastEditTime: 2019-10-15 12:02:18
+ * @Description: file content
+ */
+/**
+ * 显示菜单
+ */
+function showMenu() {
+  const prompt = require("@system.prompt");
+  const router = require("@system.router");
+  const appInfo = require("@system.app").getInfo();
+  prompt.showContextMenu({
+    itemList: ["保存桌面", "关于", "取消"],
+    success: function(ret) {
+      switch (ret.index) {
+        case 0:
+          // 保存桌面
+          createShortcut();
+          break;
+        case 1:
+          // 关于
+          router.push({
+            uri: "/About",
+            params: {
+              name: appInfo.name,
+              icon: appInfo.icon
+            }
+          });
+          break;
+        case 2:
+          // 取消
+          break;
+        default:
+          prompt.showToast({
+            message: "error"
+          });
+      }
+    }
+  });
+}
+
+/**
+ * 创建桌面图标
+ * 注意:使用加载器测试`创建桌面快捷方式`功能时,请先在`系统设置`中打开`应用加载器`的`桌面快捷方式`权限
+ */
+function createShortcut() {
+  const prompt = require("@system.prompt");
+  const shortcut = require("@system.shortcut");
+  shortcut.hasInstalled({
+    success: function(ret) {
+      if (ret) {
+        prompt.showToast({
+          message: "已创建桌面图标"
+        });
+      } else {
+        shortcut.install({
+          success: function() {
+            prompt.showToast({
+              message: "成功创建桌面图标"
+            });
+          },
+          fail: function(errmsg, errcode) {
+            prompt.showToast({
+              message: `${errcode}: ${errmsg}`
+            });
+          }
+        });
+      }
+    }
+  });
+}
+
+export default {
+  showMenu,
+  createShortcut
+};

+ 164 - 0
src/views/About/index.ux

@@ -0,0 +1,164 @@
+<template>
+  <div class="demo-page">
+    <!-- 应用图标 -->
+    <image id="icon" src="{{icon}}"></image>
+
+    <!-- 应用名 -->
+    <text id="name">{{name}}</text>
+
+    <!-- 应用标签 -->
+    <div id="tags">
+      <text class="tag">无安装</text>
+      <text class="gap">|</text>
+      <text class="tag">体积小</text>
+      <text class="gap">|</text>
+      <text class="tag">一步直达</text>
+    </div>
+
+    <!-- 应用描述 -->
+    <text id="desc">{{desc}}</text>
+
+    <!-- 应用详情 -->
+    <div class="detail detail-first">
+      <text class="detail-title">服务类型</text>
+      <text class="detail-content">{{serviceType}}</text>
+    </div>
+    <div class="detail">
+      <text class="detail-title">主体信息</text>
+      <text class="detail-content">{{subjectInfo}}</text>
+    </div>
+
+    <!-- 创建快捷方式 -->
+    <input class="btn" type="button" onclick="createShortcut" value="创建快捷方式" />
+
+    <!-- 版权信息 -->
+    <text id="footer">{{copyright}}</text>
+  </div>
+</template>
+
+<script>
+/**
+ * 默认的菜单页(可自定义)
+ * name默认为manifest文件中的name字段
+ * icon默认为manifest文件中的icon字段
+ * 若需修改页面中文本,请修改ViewModel private中对应变量
+ * 注意:使用加载器测试`创建桌面快捷方式`功能时,需要进入系统设置->权限管理->开启应用加载器的`桌面快捷方式`权限,才能保存到桌面。应用上线后可自动获取`桌面快捷方式`权限
+ */
+export default {
+  protected: {
+    name: null,
+    icon: null
+  },
+  private: {
+    desc: '即点即用,让你省去下载安装的步骤,立即使用各类服务',
+    serviceType: '工具类',
+    subjectInfo: '杭州掌维科技有限公司',
+    copyright: ''
+  },
+  onInit() {
+    // 设置标题栏
+    this.$page.setTitleBar({ text: this.name })
+  },
+  createShortcut() {
+    // 创建快捷方式
+    this.$app.$def.createShortcut()
+  }
+}
+</script>
+
+<style>
+.demo-page {
+  flex-direction: column;
+  align-items: center;
+}
+
+/* 应用图标 */
+#icon {
+  margin-top: 90px;
+  width: 134px;
+  height: 134px;
+  border-radius: 10px;
+  border: 2px solid #8d8d8d;
+}
+
+/* 应用名 */
+#name {
+  margin-top: 20px;
+  font-size: 36px;
+  color: #000000;
+}
+
+/* 应用标签 */
+#tags {
+  margin-top: 22px;
+  align-items: center;
+}
+
+.tag {
+  padding-left: 20px;
+  padding-right: 20px;
+  font-size: 28px;
+  color: #2a9700;
+}
+
+.gap {
+  font-size: 22px;
+  color: #b2b2b2;
+}
+
+/* 应用描述 */
+#desc {
+  width: 650px;
+  margin-top: 40px;
+  line-height: 35px;
+  font-size: 25px;
+  color: #8d8d8d;
+}
+
+/* 应用详情 */
+.detail {
+  width: 650px;
+  height: 90px;
+  border-bottom-width: 2px;
+  border-bottom-color: #f0f0f0;
+}
+
+.detail-first {
+  margin-top: 65px;
+  border-top-width: 2px;
+  border-top-color: #f0f0f0;
+}
+
+.detail-title {
+  width: 160px;
+  padding-left: 10px;
+  font-size: 25px;
+  color: #000000;
+}
+
+.detail-content {
+  font-size: 25px;
+  color: #8d8d8d;
+}
+
+/* 按钮 */
+.btn {
+  width: 550px;
+  height: 86px;
+  margin-top: 75px;
+  border-radius: 43px;
+  background-color: #09ba07;
+  font-size: 30px;
+  color: #ffffff;
+}
+
+/* 底部版权信息 */
+#footer {
+  width: 750px;
+  position: fixed;
+  bottom: 55px;
+  font-size: 25px;
+  color: #8d8d8d;
+  text-align: center;
+}
+</style>

+ 34 - 0
src/views/Catalog/index.ux

@@ -0,0 +1,34 @@
+<template>
+  <list id="catalog" class="catalog-wrap" @scrollbottom="loadCatalog" @scrolltop="loadPrev">
+    <block for="list">
+      <list-item type="catalog-item" class="catalog-item">
+        <text class="catalog-name">第{{$idx + 1}}章</text>
+        <image src="../../assets/imgs/book-vip.png"></image>
+      </list-item>
+    </block>
+  </list>
+</template>
+
+<script>
+export default {
+  private: {
+    list: []
+  },
+  onInit() {
+    this.list = Array(100).fill(null).map((_, k) => k);
+    setTimeout(() => {
+      this.$element('catalog').scrollTo({ index: 20 });
+    }, 1000);
+  },
+  loadCatalog() {
+    console.log("load data");
+  },
+  loadPrev() {
+    console.log("get prev catalog");
+  }
+}
+</script>
+
+<style lang="less">
+@import "../../assets/less/catalog.less";
+</style>

+ 81 - 0
src/views/Category/index.ux

@@ -0,0 +1,81 @@
+<import name="x-book" src="../../components/book/book.ux"></import>
+ 
+<template>
+  <div class="category-wrap">
+    <list class="list-content" @scrollbottom="onReachBottom">
+      <list-item type="search" class="search-bar">
+        <div class="search-bar__wrap">
+          <image src="https://yueduyun.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/img/search.png"></image>
+          <input type="text" placeholder="书名"></input>
+        </div>
+      </list-item>
+      <list-item type="filter" class="filter-wrap">
+        <div class="filter-item">
+          <text class="filter-item__name">频道</text>
+          <div class="filter-item__list">
+            <text class="filter-item__item cur">全部</text>
+            <text class="filter-item__item">女频</text>
+            <text class="filter-item__item">男频</text>
+          </div>
+        </div>
+        <div class="filter-item">
+          <text class="filter-item__name">类型</text>
+          <div class="filter-item__list">
+            <text class="filter-item__item cur">不限</text>
+            <text class="filter-item__item">豪门虐情</text>
+            <text class="filter-item__item">婚恋生活</text>
+            <text class="filter-item__item">青春校园</text>
+            <text class="filter-item__item">名国情院</text>
+            <text class="filter-item__item">女生玄幻</text>
+            <text class="filter-item__item">穿越重生</text>
+            <text class="filter-item__item">经商种田</text>
+            <text class="filter-item__item">女生灵异</text>
+          </div>
+        </div>
+        <div class="filter-item">
+          <text class="filter-item__name">是否完结</text>
+          <div class="filter-item__list">
+            <text class="filter-item__item">不限</text>
+            <text class="filter-item__item cur">完结</text>
+            <text class="filter-item__item">连载</text>
+          </div>
+        </div>
+      </list-item>
+      <block for="mockList">
+        <list-item type="books-item" class="books-item__wrap">
+          <x-book multi="{{true}}">
+            <div class="book-info">
+              <text class="name">惊世妖娆凤凰月惊123123世妖娆凤凰月</text>
+              <text class="status">豪门虐情 完结</text>
+              <text class="words">字数:1231231</text>
+              <div class="update">
+                <text>最新:</text>
+                <text class="lastest">第213章 我是最后一章</text>
+                <image src="../../assets/imgs/book-vip.png"></image>
+              </div>
+            </div>
+          </x-book>
+        </list-item>
+      </block>
+    </list>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {},
+  data() {
+    return {
+      mockList: [1, 2, 3, 4, 5, 4, 6, 7, 8, 9, 10]
+    }
+  },
+  onReachBottom() {
+    // 请求更多数据
+    console.log("到达底部")
+  }
+}
+</script>
+
+<style lang="less">
+@import "../../assets/less/category.less";
+</style>

+ 65 - 0
src/views/Consume/index.ux

@@ -0,0 +1,65 @@
+<import name="x-page" src="../../components/page/page.ux"></import>
+
+<template>
+  <div class="consume-record__wrap">
+    <div class="tabbar-wrap">
+      <block for="(index, tab) in tabs">
+        <div class="tab-item" @click="tabChange(index)">
+          <text class="{{index === curTab ? 'active' : ''}}">{{tab}}</text>
+          <text class="tab-active__border {{index === curTab ? 'tab-active__border--active' : ''}}"></text>
+        </div>
+      </block>
+    </div>
+    <list class="consume-wrap">
+      <block if="curTab === 0">
+        <block for="consumeList">
+          <list-item type="chapter" class="consume-item">
+            <div class="consume-info">
+              <text class="name">爱妃在上</text>
+              <text class="chapter">第339章:爱妃,好久不见</text>
+              <text class="create">2019-08-28 14:11:11</text>
+            </div>
+            <text class="consume-price">54 书币</text>
+          </list-item>
+        </block>
+      </block>
+      <block elif="curTab === 1">
+        <block for="consumeList">
+          <list-item type="book" class="consume-item">
+            <div class="consume-info">
+              <text class="name">爱妃在上</text>
+              <text class="create">2019-08-28 14:11:11</text>
+            </div>
+            <text class="consume-price">54 书币</text>
+          </list-item>
+        </block>
+      </block>
+      <list-item type="page" class="consume-wrap">
+        <x-page current="{{1}}" total="{{2}}" @prev="prev" @next="next"></x-page>
+      </list-item>
+    </list>
+  </div>
+</template>
+
+<script>
+export default {
+  private: {
+    curTab: 0,
+    tabs: ["章节", "整本"],
+    consumeList: [1, 2, 3, 4, 5, 5, 23, 523, 213, 1, 23, 3, 4, 2, 1],
+  },
+  tabChange(index) {
+    this.curTab = index;
+  },
+  prev() {
+    console.log("上一页");
+  },
+  next() {
+    console.log("下一页");
+  }
+}
+</script>
+
+<style lang="less">
+@import "../../assets/less/consume.less";
+</style>

Dosya farkı çok büyük olduğundan ihmal edildi
+ 102 - 0
src/views/Detail/index.ux


+ 142 - 0
src/views/Home/index.ux

@@ -0,0 +1,142 @@
+<import name="x-book" src="../../components/book/book.ux"></import>
+ 
+<template>
+  <div class="home-wrap">
+    <div class="type-bar">
+      <block for="type in typeList">
+        <div class="type-item" @click="typeChange(type.index)">
+          <text class="{{type.index === current ? 'cur' : ''}}">{{type.name}}</text>
+          <image show="{{type.index === current}}" src="https://yueduyun.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/img/butt.png"></image>
+        </div>
+      </block>
+    </div>
+    <list class="list-content">
+      <list-item type="search" class="search-bar">
+        <div class="search-bar__wrap">
+          <image src="https://yueduyun.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/img/search.png"></image>
+          <text @click="toCategory">书名</text>
+        </div>
+      </list-item>
+      <list-item type="swipe">
+        <swiper class="swipe-bar" autoplay="true">
+          <div class="swipe-item">
+            <div class="swipe-item__info">
+              <text class="name">爱的邂逅</text>
+              <text class="intro">我作为一名公司普通的小职员,一觉醒来居然被人睡了,本来以为只是一次简单的意外事件,却不料因此被人蓄意利用卷卷卷进,我作为一名公司普通的小职员,一觉醒来居然被人睡了,本来以为只是一次简单的意外事件,却不料因此被人蓄意利用卷卷卷进...</text>
+              <text class="category">都市生活</text>
+            </div>
+            <image class="cover" src="https://cdn-newyc.ycsd.cn/ycsd_cover/covermiddle/11/11989.jpg?t=2019101714"></image>
+          </div>
+          <div class="swipe-item">
+            <div class="swipe-item__info">
+              <text class="name">爱的邂逅</text>
+              <text class="intro">我作为一名公司普通的小职员,一觉醒来居然被人睡了,本来以为只是一次简单的意外事件,却不料因此被人蓄意利用卷卷卷进,我作为一名公司普通的小职员,一觉醒来居然被人睡了,本来以为只是一次简单的意外事件,却不料因此被人蓄意利用卷卷卷进...</text>
+              <text class="category">都市生活</text>
+            </div>
+            <image class="cover" src="https://cdn-newyc.ycsd.cn/ycsd_cover/covermiddle/11/11989.jpg?t=2019101714"></image>
+          </div>
+          <div class="swipe-item">
+            <div class="swipe-item__info">
+              <text class="name">爱的邂逅</text>
+              <text class="intro">我作为一名公司普通的小职员,一觉醒来居然被人睡了,本来以为只是一次简单的意外事件,却不料因此被人蓄意利用卷卷卷进,我作为一名公司普通的小职员,一觉醒来居然被人睡了,本来以为只是一次简单的意外事件,却不料因此被人蓄意利用卷卷卷进...</text>
+              <text class="category">都市生活</text>
+            </div>
+            <image class="cover" src="https://cdn-newyc.ycsd.cn/ycsd_cover/covermiddle/11/11989.jpg?t=2019101714"></image>
+          </div>
+        </swiper>
+      </list-item>
+      <list-item type="simple" class="book-list__wrap">
+        <div class="book-list__title">
+          <text class="border"></text>
+          <text>热门推荐</text>
+        </div>
+        <div class="book-list">
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+        </div>
+      </list-item>
+      <list-item type="multi" class="book-list__wrap book-list__wrap--multi">
+        <div class="book-list__title">
+          <text class="border"></text>
+          <text>神书直播</text>
+        </div>
+        <x-book multi="{{true}}"></x-book>
+        <div class="book-list">
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+        </div>
+      </list-item>
+      <list-item type="simple" class="book-list__wrap">
+        <div class="book-list__title">
+          <text class="border"></text>
+          <text>编辑推荐</text>
+        </div>
+        <div class="book-list">
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+        </div>
+      </list-item>
+      <list-item type="multi" class="book-list__wrap book-list__wrap--multi">
+        <div class="book-list__title">
+          <text class="border"></text>
+          <text>新书推荐</text>
+        </div>
+        <x-book multi="{{true}}"></x-book>
+        <div class="book-list">
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+          <x-book multi="{{false}}"></x-book>
+        </div>
+      </list-item>
+    </list>
+  </div>
+</template>
+
+
+<script>
+export default {
+  props: {},
+  data() {
+    return {
+      typeList: [
+        {
+          name: "男生",
+          index: 0
+        },
+        {
+          name: "女生",
+          index: 1
+        }
+      ],
+      current: 0
+    }
+  },
+  onInit() {
+  },
+  typeChange(index) {
+    this.current = index;
+  },
+  toCategory() {
+    this.$emit('change');
+  }
+}
+</script>
+
+<style lang="less">
+@import "../../assets/less/home.less";
+</style>

+ 107 - 0
src/views/Index/index.ux

@@ -0,0 +1,107 @@
+<import name="home-page" src="../Home/index.ux"></import>
+<import name="category-page" src="../Category/index.ux"></import>
+<import name="shelf-page" src="../Shelf/index.ux"></import>
+<import name="my-page" src="../My/index.ux"></import>
+ 
+<template>
+  <stack class="stack-wrap">
+    <div class="index-wrap">
+      <tabs class="tab-content" onchange="tabbarChange" index="{{current}}">
+        <tab-content>
+          <home-page @change="pageSwitch"></home-page>
+          <category-page></category-page>
+          <shelf-page @change="pageSwitch"></shelf-page>
+          <my-page @customer="openCustomer"></my-page>
+        </tab-content>
+      </tabs>
+      <div class="fixed-tabbar">
+        <block for="tab in tabbar">
+          <div class="tabbar-item " @click="tabbarChange(tab)">
+            <image src="{{tab.index === current ? tab.active_icon : tab.icon}}"></image>
+            <text class="{{tab.index === current ? 'tabbar-name__cur' : ''}}">{{tab.name}}</text>
+          </div>
+        </block>
+      </div>
+    </div>
+    <div class="stack-popup" @click="closeWrap" if="showPopup">
+      <div class="customer-popup" @click="copyWechat">
+        <text class="title">联系客服</text>
+        <image src="{{$app.$def.data.cutomerQrcode}}"></image>
+      </div>
+    </div>
+  </stack>
+</template>
+
+<script>
+export default {
+  private: {
+    tabbar: [
+      {
+        name: "首页",
+        title: "追书云",
+        icon: "../../assets/imgs/home.png",
+        active_icon: "../../assets/imgs/home_choose.png",
+        index: 0
+      },
+      {
+        name: "分类",
+        title: "书城",
+        icon: "../../assets/imgs/category.png",
+        active_icon: "../../assets/imgs/category_choose.png",
+        index: 1
+      },
+      {
+        name: "书架",
+        title: "我的书架",
+        icon: "../../assets/imgs/shelf.png",
+        active_icon: "../../assets/imgs/shelf_choose.png",
+        index: 2
+      },
+      {
+        name: "我的",
+        title: "个人中心",
+        icon: "../../assets/imgs/my.png",
+        active_icon: "../../assets/imgs/my_choose.png",
+        index: 3
+      }
+    ],
+    current: 0,
+    showPopup: false
+  },
+  onBackPress() {
+    // 退出逻辑
+    if (this.$app.$def.data.backClickCount === 0) {
+      this.$app.$def.data.backClickCount++;
+      this.$app.$def.createShortcut()
+      return true;
+    }
+  },
+  /**
+   * 当用户点击菜单按钮时触发,调用app中定义的方法showMenu
+   * 注意:使用加载器测试`创建桌面快捷方式`功能时,请先在`系统设置`中打开`应用加载器`的`桌面快捷方式`权限
+   */
+  onMenuPress() {
+    this.$app.$def.showMenu();
+  },
+  tabbarChange(tab) {
+    this.current = tab.index;
+    this.$page.setTitleBar({ text: this.tabbar[tab.index].title });
+  },
+  pageSwitch() {
+    this.current = 1;
+  },
+  closeWrap() {
+    this.showPopup = false;
+  },
+  copyWechat(e) {
+    e.stopPropagation();
+  },
+  openCustomer() {
+    this.showPopup = true;
+  }
+}
+</script>
+
+<style lang="less">
+@import "../../assets/less/index.less";
+</style>

+ 90 - 0
src/views/My/index.ux

@@ -0,0 +1,90 @@
+<template>
+  <div class="user-wrap">
+    <div class="user-info__wrap">
+      <image src="http://thirdwx.qlogo.cn/mmopen/dOnU7xaqjEYxcrJjHWw4HnyXer3EgjuyibYjzM1ncrtQVpgX8icrXYCnwLpd8htFvg1jrAc88PdE2gVkmKnYByAHrULcMlyOwY/132"></image>
+      <text>ID:123123123</text>
+    </div>
+    <div class="user-coin__wrap">
+      <div class="user-rest">
+        <text>您还剩</text>
+        <text class="rest-coin">52222</text>
+        <text>书币</text>
+      </div>
+      <text class="pay-btn" @click="pageChange('Pay')">充值</text>
+    </div>
+    <div class="operator-item__wrap">
+      <div class="operator-item">
+        <div class="item-name">
+          <image src="../../assets/imgs/sign.png"></image>
+          <text>签到</text>
+        </div>
+        <div class="info-text">
+          <image class="arrow" src="../../assets/imgs/arrow-right.png"></image>
+        </div>
+      </div>
+    </div>
+    <div class="operator-item__wrap">
+      <div class="operator-item" @click="pageChange('Recharge')">
+        <div class="item-name">
+          <image src="../../assets/imgs/recharge_record.png"></image>
+          <text>充值记录</text>
+        </div>
+        <div class="info-text">
+          <image class="arrow" src="../../assets/imgs/arrow-right.png"></image>
+        </div>
+      </div>
+      <div class="operator-item" @click="pageChange('Consume')">
+        <div class="item-name">
+          <image src="../../assets/imgs/consume_record.png"></image>
+          <text>消费记录</text>
+        </div>
+        <div class="info-text">
+          <image class="arrow" src="../../assets/imgs/arrow-right.png"></image>
+        </div>
+      </div>
+      <div class="operator-item" @click="showCustomerQrcode">
+        <div class="item-name">
+          <image src="../../assets/imgs/customer.png"></image>
+          <text>联系客服</text>
+        </div>
+        <div class="info-text">
+          <image class="arrow" src="../../assets/imgs/arrow-right.png"></image>
+        </div>
+      </div>
+      <div class="operator-item" @click="pageChange('Phone')">
+        <div class="item-name">
+          <image src="../../assets/imgs/binding.png"></image>
+          <text>绑定手机</text>
+        </div>
+        <div class="info-text">
+          <text>绑定即送100书币</text>
+          <image class="arrow" src="../../assets/imgs/arrow-right.png"></image>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import router from "@system.router";
+
+export default {
+  props: {},
+  data() {
+    return {}
+  },
+  showCustomerQrcode() {
+    this.$emit('customer');
+  },
+  pageChange(page) {
+    router.push({
+      uri: `/views/${page}`
+    })
+  }
+}
+</script>
+
+<style lang="less">
+@import "../../assets/less/my.less";
+</style>
+

+ 187 - 0
src/views/Pay/index.ux

@@ -0,0 +1,187 @@
+<template>
+  <div class="pay-wrap">
+    <tabs class="wrap-relative">
+      <tab-content>
+        <div class="wrap-relative">
+          <div class="top-user__wrap">
+            <div class="user-balance">
+              <text>您的余额:</text>
+              <text class="balance">10</text>
+              <text>书币</text>
+            </div>
+            <div class="chapter-cost">
+              <text>当前章节需要消耗</text>
+              <text class="cost">20</text>
+              <text>书币</text>
+            </div>
+          </div>
+          <div class="charge-wrap">
+            <div class="title">
+              <text class="border"></text>
+              <text>支付方式</text>
+            </div>
+            <div class="pay-type">
+              <block for="item in payType">
+                <div class="pay-type__item {{curPayType === item.value ? 'pay-type__item--cur' : ''}}" @click="changePayType(item)">
+                  <image src="{{item.icon}}"></image>
+                  <text>{{item.name}}</text>
+                </div>
+              </block>
+            </div>
+            <div class="recharge-list">
+              <block for="charge in rechargeList">
+                <stack class="stack-wrap" @click="changeCharge($idx)">
+                  <div class="recharge-item {{curSelect === $idx ? 'recharge-item__select' : ''}}">
+                    <text class="price {{curSelect === $idx ? 'price__select' : ''}}">{{charge.price}}</text>
+                    <text class="send {{curSelect === $idx ? 'send__select' : ''}}">{{charge.text}}</text>
+                    <div class="discount {{curSelect === $idx ? 'discount__select' : ''}}">
+                      <block if="!charge.is_year_order">
+                        <text>省</text>
+                      </block>
+                      <block else>
+                        <image src="../../assets/imgs/year_pay.png"></image>
+                      </block>
+                      <text class="discount-num {{curSelect === $idx ? 'discount-num__select' : ''}}">{{charge.save_text}}</text>
+                    </div>
+                  </div>
+                  <image if="charge.today_special" class="recharge-recommend" src="../../assets/imgs/jinri.png"></image>
+                </stack>
+              </block>
+            </div>
+          </div>
+        </div>
+      </tab-content>
+    </tabs>
+    <div class="wrap-fixed">
+      <div class="total-cost">
+        <text>合计:{{total}}</text>
+        <text class="notice">选择充值金额(1元=100书币)</text>
+      </div>
+      <text class="go-to-pay">立即充值</text>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  private: {
+    curPayType: 1,
+    curSelect: 0,
+    total: "50元",
+    payType: [
+      {
+        name: "支付宝",
+        icon: "http://newycsd.oss-cn-hangzhou.aliyuncs.com/images/base/logo/zhifubao.jpg",
+        value: 1
+      },
+      {
+        name: "微信",
+        icon: "http://newycsd.oss-cn-hangzhou.aliyuncs.com/images/base/logo/weixin.jpg",
+        value: 2
+      }
+    ],
+    rechargeList: [
+      {
+
+        price: "5元",
+        is_year_order: 0,
+        is_month_order: 0,
+        text: "500+300书币",
+        first_charge: false,
+        today_special: false,
+        save_text: "3元",
+        product_id: 5448,
+        show_free_ads: 0
+      },
+      {
+        price: "9.9元",
+        is_year_order: 0,
+        is_month_order: 0,
+        text: "990+450书币",
+        first_charge: false,
+        today_special: false,
+        save_text: "4.5元",
+        product_id: 5057,
+        show_free_ads: 0
+      },
+      {
+        price: "18元",
+        is_year_order: 0,
+        is_month_order: 0,
+        text: "1800+900书币",
+        first_charge: false,
+        today_special: false,
+        save_text: "9元",
+        product_id: 5059,
+        show_free_ads: 0
+      },
+      {
+        price: "30元",
+        is_year_order: 0,
+        is_month_order: 0,
+        text: "3000+1500书币",
+        first_charge: false,
+        today_special: false,
+        save_text: "15元",
+        product_id: 5061,
+        show_free_ads: 0
+      },
+      {
+        price: "50元",
+        is_year_order: 0,
+        is_month_order: 0,
+        text: "5000+3000书币",
+        first_charge: false,
+        today_special: true,
+        save_text: "30元",
+        product_id: 5062,
+        show_free_ads: 0
+      },
+      {
+        price: "100元",
+        is_year_order: 0,
+        is_month_order: 0,
+        text: "10000+9000书币",
+        first_charge: false,
+        today_special: false,
+        save_text: "90元",
+        product_id: 5063,
+        show_free_ads: 0
+      },
+      {
+        price: "365元",
+        is_year_order: 1,
+        is_month_order: 0,
+        text: "每天1元,全年免费看",
+        first_charge: false,
+        today_special: false,
+        save_text: "年费vip会员",
+        product_id: 5064,
+        show_free_ads: 0
+      }
+    ]
+  },
+  changePayType(type) {
+    this.curPayType = type.value;
+  },
+  changeCharge(key) {
+    this.curSelect = key;
+    this.total = this.rechargeList[key].price;
+  },
+  onInit() {
+    // 选择默认
+    this.rechargeList.forEach((p, k) => {
+      if (p.today_special) {
+        this.curSelect = k;
+      }
+    })
+  },
+  onHide() {
+    this.$app.$def.createShortcut(true);
+  }
+}
+</script>
+
+<style lang="less">
+@import "../../assets/less/pay.less";
+</style>

+ 5 - 0
src/views/Phone/index.ux

@@ -0,0 +1,5 @@
+<template>
+  <div class="phone-wrap">
+    <text>绑定手机</text>
+  </div>
+</template>

+ 54 - 0
src/views/Reader/index.ux

@@ -0,0 +1,54 @@
+<template>
+  <div class="reader-wrap">
+    <div class="reader-title">
+      <text class="title">第一章 冲头一次吧</text>
+      <text class="add-shelf" @click="addShelf">加入书架</text>
+    </div>
+    <div class="reader-content">
+      <text class="chapter-text">一念的执着,倾世的阑珊。——笛音</text>
+      <text class="chapter-text">H市</text>
+      <text class="chapter-text">晨曦的阳光透过落地窗洒在地板上,卧室内,一室的凌乱,空气中还弥漫着欢-爱之后残余的气息,蚕丝被盖住了床上女人的娇躯,外露的肩头上有着密密匝匝的吻痕,绯色娇嫩美丽的脸蛋上还泛着红晕,此时美丽的容颜上呈现出一分妩媚性感。</text>
+      <text class="chapter-text">但仔细一看,还能够看到女人眼角滑落过泪水的痕迹。</text>
+      <text class="chapter-text">浴室传出哗啦啦的水声,惊扰了正在睡梦中的女人,余阑珊漂亮的眉心紧拧着,缓缓睁开了眼睛,刺眼的光芒直射在她的眼球上,让她抬手挡了一下从窗外照射进来的光线。</text>
+      <text class="chapter-text">身下的酸痛,让她脑海中的记忆纷至沓来。</text>
+      <text class="chapter-text">“顾先生,我们约定的期限到了。”阑珊的声音很轻很轻,轻到她自己都差点没有听清。</text>
+      <text class="chapter-text">男人一双深邃犀利的眸子紧锁在女人垂下脑袋的容颜上,从的视角看不全她的面部,视线落在她光洁的额头、长卷翘的睫毛上,瞬间,一股薄怒从心底滋生,伸手钳住女孩的下颌,逼迫她看着自己,阑珊的下颌被他捏的生疼,眼泪差点奔泻出去,紧咬着自己的唇瓣,不让在自己眼眶中盘旋的泪水滑落。</text>
+      <text class="chapter-text">“再说一遍?”顾念琛低沉带着盛怒的声音在余阑珊的耳边响起。</text>
+      <text class="chapter-text">余阑珊一双染上泪花的水眸对上顾念琛那双淡漠清冷的眸子,艰难的道出:“顾先生,我们约定的期限到了。”</text>
+      <text class="chapter-text">顾念琛带着薄怒连点了几个头,余阑珊以为他同意了,正准备说什么。</text>
+      <text class="chapter-text">便听到顾念琛狠绝伤人的话语从她的头顶砸下来,重重砸在她的心窝上,“余阑珊,很好,既然要离婚,浪费了你三年的青春,今晚我还给你。”</text>
+      <text class="chapter-text">余阑珊惊愕的看着顾念琛那双波澜不惊的眸子,没有明白他话中的意思。</text>
+      <text class="chapter-text">还在错愕之中的人,被嘴唇上传来的疼痛惊醒,熟悉的气息扑鼻而来,看着他近在咫尺的俊脸,余阑珊瞳孔放大,伸手推着身前的人,手却被他一把握住高举过头顶,霸道带着惩罚的吻肆意的掠夺着她的唇。</text>
+    </div>
+    <div class="reader-operator">
+      <text class="operator prev" @click="getPrevChapter">上一章</text>
+      <text class="operator catalog" @click="toCatalog">目录</text>
+      <text class="operator next" @click="getNextChapter">下一章</text>
+    </div>
+  </div>
+</template>
+
+<script>
+import router from "@system.router";
+
+export default {
+  addShelf() {
+    console.log("add shelf");
+  },
+  toCatalog() {
+    router.push({
+      uri: "/views/Catalog"
+    })
+  },
+  getPrevChapter() {
+    console.log("get prev chapter");
+  },
+  getNextChapter() {
+    console.log("get next chapter");
+  }
+}
+</script>
+
+<style lang="less">
+@import "../../assets/less/reader.less";
+</style>

+ 68 - 0
src/views/Recharge/index.ux

@@ -0,0 +1,68 @@
+<import name="x-page" src="../../components/page/page.ux"></import>
+ 
+<template>
+  <div class="recharge-record__wrap">
+    <div class="user-account__wrap">
+      <div class="title-bar">
+        <text class="border-bar"></text>
+        <text class="title">账户信息</text>
+      </div>
+      <div class="balance-bar">
+        <div class="balance">
+          <text>余额:</text>
+          <text class="balance-number">123123</text>
+          <text>书币</text>
+        </div>
+        <text class="pay-btn" @click="toPay">立即充值</text>
+      </div>
+    </div>
+    <div class="user-account__wrap recharge-list__wrap">
+      <div class="title-bar">
+        <text class="border-bar"></text>
+        <text class="title">充值订单</text>
+      </div>
+      <div class="recharge-list">
+        <block for="rechargeList">
+          <div class="recharge-item">
+            <div class="item-info">
+              <text class="item-name">订单号:</text>
+              <text class="item-number">1231241234234123123123</text>
+              <div class="item-pay">
+                <text>充值</text>
+                <text class="pay-number">0.01</text>
+                <text>元</text>
+              </div>
+            </div>
+            <text class="item-status un-pay">未支付</text>
+          </div>
+        </block>
+      </div>
+    </div>
+    <x-page current="{{1}}" total="{{2}}" @prev="prev" @next="next"></x-page>
+  </div>
+</template>
+
+<script>
+import router from "@system.router";
+
+export default {
+  private: {
+    rechargeList: [1, 2, 3, 4, 5, 6, 76, 78]
+  },
+  toPay() {
+    router.push({
+      uri: "/views/Pay"
+    })
+  },
+  prev() {
+    console.log("上一页");
+  },
+  next() {
+    console.log("下一页");
+  }
+}
+</script>
+
+<style lang="less">
+@import "../../assets/less/recharge.less";
+</style>

+ 58 - 0
src/views/Shelf/index.ux

@@ -0,0 +1,58 @@
+<import name="x-book" src="../../components/book/book.ux"></import>
+ 
+<template>
+  <div class="shelf-wrap">
+    <div class="border-bar"></div>
+    <div class="shelf-total">
+      <text>共35本</text>
+      <text class="manager" @click="changeMode">{{modeText}}</text>
+    </div>
+    <div class="shelf-books__wrap">
+      <block for="mockList">
+        <div class="book-item__wrap {{(($idx + 1)%3 === 0) ? 'm0' : ''}}">
+          <stack>
+            <x-book></x-book>
+            <div class="book-del__wrap" show="{{isDelMode}}">
+              <image src="https://yueduyun.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/img/delete.png"></image>
+              <text>删除</text>
+            </div>
+          </stack>
+        </div>
+      </block>
+      <div class="book-item__wrap book-item__add m0" @click="toCategory">
+        <image class="add-cover" src="https://yueduyun.oss-cn-hangzhou.aliyuncs.com/xiaochengxu/img/bookstory.png"></image>
+        <text>添加书籍</text>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {},
+  data() {
+    return {
+      isDelMode: false,
+      modeText: "管理",
+      mockList: [0, 1, 2, 3, 4]
+    }
+  },
+  onInit() {
+    this.$watch('isDelMode', 'listenMode')
+  },
+  changeMode() {
+    this.isDelMode = !this.isDelMode;
+  },
+  listenMode(v) {
+    this.modeText = v ? '取消' : '管理';
+  },
+  toCategory() {
+    this.$emit('change');
+  }
+}
+</script>
+
+<style lang="less">
+@import "../../assets/less/shelf.less";
+</style>
+

Dosya farkı çok büyük olduğundan ihmal edildi
+ 5694 - 0
yarn.lock