Pārlūkot izejas kodu

Merge branch '抽奖'

# Conflicts:
#	manifest.json
xiaohaizhao 1 gadu atpakaļ
vecāks
revīzija
39cb80d9fe
41 mainītis faili ar 2956 papildinājumiem un 58 dzēšanām
  1. 1 0
      cloud/collect/mylist.vue
  2. 1 0
      cloud/designReality/index.vue
  3. BIN
      components/.DS_Store
  4. BIN
      components/@lucky-canvas/.DS_Store
  5. 201 0
      components/@lucky-canvas/uni/LICENSE
  6. 138 0
      components/@lucky-canvas/uni/README.md
  7. 317 0
      components/@lucky-canvas/uni/lucky-grid.vue
  8. 255 0
      components/@lucky-canvas/uni/lucky-wheel.vue
  9. 23 0
      components/@lucky-canvas/uni/package.json
  10. 214 0
      components/@lucky-canvas/uni/slot-machine.vue
  11. 82 0
      components/@lucky-canvas/uni/utils.js
  12. 3 2
      components/My_listbox.vue
  13. 201 0
      components/lucky-canvas/LICENSE
  14. 42 0
      components/lucky-canvas/README.md
  15. 15 0
      components/lucky-canvas/dist/index.cjs.js
  16. 0 0
      components/lucky-canvas/dist/index.cjs.js.map
  17. 14 0
      components/lucky-canvas/dist/index.esm.js
  18. 0 0
      components/lucky-canvas/dist/index.esm.js.map
  19. 14 0
      components/lucky-canvas/dist/index.umd.js
  20. 0 0
      components/lucky-canvas/dist/index.umd.js.map
  21. 14 0
      components/lucky-canvas/dist/lucky-canvas.js
  22. 1 0
      components/lucky-canvas/index.js
  23. 66 0
      components/lucky-canvas/package.json
  24. 752 0
      components/lucky-canvas/types/index.d.ts
  25. 1 0
      packageA/affiche/index.vue
  26. 1 0
      packageA/exam/index.vue
  27. 2 1
      packageA/exam/result.vue
  28. 1 0
      packageA/resourceLibrary/index.vue
  29. 4 0
      pages.json
  30. 93 55
      pages/index/index.vue
  31. 1 0
      pages/index/index/casePages/design.vue
  32. 1 0
      store/center/detail.vue
  33. 1 0
      store/deliveryAddress/index.vue
  34. 1 0
      store/insert/member.vue
  35. 395 0
      store/lottery/modules/sudoku.vue
  36. 56 0
      store/lottery/shareable.vue
  37. 41 0
      store/lottery/unshareable.vue
  38. 1 0
      team/agency/check.vue
  39. 1 0
      team/team/modules/agency.vue
  40. 1 0
      team/team/modules/store.vue
  41. 1 0
      team/team/modules/users.vue

+ 1 - 0
cloud/collect/mylist.vue

@@ -97,6 +97,7 @@ export default {
                     if (this.cutoff(res.msg)) return;
                     res.data = this.$refs[current.name].handleList(res.data)
                     this.list = res.data;
+                    this.$refs.List.paging(current, res, true)
                 })
             }
         },

+ 1 - 0
cloud/designReality/index.vue

@@ -73,6 +73,7 @@ export default {
                         return v
                     })
                     this.list = res.data;
+                    this.$refs.List.paging(current, res, true)
                     if (data) handle();
                 })
                 function handle() {

BIN
components/.DS_Store


BIN
components/@lucky-canvas/.DS_Store


+ 201 - 0
components/@lucky-canvas/uni/LICENSE

@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [2021] [Li Dong Qi]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 138 - 0
components/@lucky-canvas/uni/README.md

@@ -0,0 +1,138 @@
+<br />
+
+<div align="center">
+  <img src="https://cdn.jsdelivr.net/gh/buuing/cdn/imgs/lucky-canvas.jpg" width="210" alt="logo" />
+  <h1>lucky-canvas 抽奖插件</h1>
+  <p>一个基于 JavaScript 的跨平台 ( 大转盘 / 九宫格 / 老虎机 ) 抽奖插件</p>
+  <p>
+    <a href="https://github.com/buuing/lucky-canvas/stargazers" target="_black">
+      <img src="https://img.shields.io/github/stars/buuing/lucky-canvas?color=%23ffba15&logo=github&style=flat-square" alt="stars" />
+    </a>
+    <a href="https://github.com/buuing/lucky-canvas/network/members" target="_black">
+      <img src="https://img.shields.io/github/forks/buuing/lucky-canvas?color=%23ffba15&logo=github&style=flat-square" alt="forks" />
+    </a>
+    <a href="https://github.com/buuing" target="_black">
+      <img src="https://img.shields.io/badge/Author-%20buuing%20-7289da.svg?&logo=github&style=flat-square" alt="author" />
+    </a>
+    <a href="https://github.com/buuing/lucky-canvas/blob/master/LICENSE" target="_black">
+      <img src="https://img.shields.io/github/license/buuing/lucky-canvas?color=%232dce89&logo=github&style=flat-square" alt="license" />
+    </a>
+  </p>
+</div>
+
+
+|适配框架|npm下载量|CDN使用量|
+| :-: | :-: | :-: |
+|[`JS` / `JQ` 中使用](https://100px.net/usage/js.html)|<a href="https://www.npmjs.com/package/lucky-canvas" target="_black"><img src="https://img.shields.io/npm/dm/lucky-canvas?color=%23ffba15&logo=npm&style=flat-square" alt="downloads" /></a>|<a href="https://www.jsdelivr.com/package/npm/lucky-canvas" target="_black"><img src="https://data.jsdelivr.com/v1/package/npm/lucky-canvas/badge" alt="downloads" /></a>|
+|[`Vue` 中使用](https://100px.net/usage/vue.html)|<a href="https://www.npmjs.com/package/@lucky-canvas/vue" target="_black"><img src="https://img.shields.io/npm/dm/@lucky-canvas/vue?color=%23ffba15&logo=npm&style=flat-square" alt="downloads" /></a>|<a href="https://www.jsdelivr.com/package/npm/@lucky-canvas/vue" target="_black"><img src="https://data.jsdelivr.com/v1/package/npm/@lucky-canvas/vue/badge" alt="downloads" /></a>|
+|[`React` 中使用](https://100px.net/usage/react.html)|<a href="https://www.npmjs.com/package/@lucky-canvas/react" target="_black"><img src="https://img.shields.io/npm/dm/@lucky-canvas/react?color=%23ffba15&logo=npm&style=flat-square" alt="downloads" /></a>|-|
+|[`UniApp` 中使用](https://100px.net/usage/uni.html)|<a href="https://www.npmjs.com/package/@lucky-canvas/uni" target="_black"><img src="https://img.shields.io/npm/dm/@lucky-canvas/uni?color=%23ffba15&logo=npm&style=flat-square" alt="downloads" /></a>|-|
+|[`Taro3.x` 中使用](https://100px.net/usage/taro.html)|<a href="https://www.npmjs.com/package/@lucky-canvas/taro" target="_black"><img src="https://img.shields.io/npm/dm/@lucky-canvas/taro?color=%23ffba15&logo=npm&style=flat-square" alt="downloads" /></a>|-|
+|[`微信小程序` 中使用](https://100px.net/usage/wx.html)|<a href="https://www.npmjs.com/package/@lucky-canvas/mini" target="_black"><img src="https://img.shields.io/npm/dm/@lucky-canvas/mini?color=%23ffba15&logo=npm&style=flat-square" alt="downloads" /></a>|-|
+
+<br />
+
+## 官方文档 & Demo演示
+
+> **中文**:[https://100px.net](https://100px.net)
+
+> **English**:**If anyone can help translate the document, please contact me** `ldq404@qq.com`
+  
+<br />
+
+## 在 uni-app 中使用
+
+### 1. 安装插件
+
+- 你可以选择通过 `HBuilderX` 导入插件: [https://ext.dcloud.net.cn/plugin?id=3499](https://ext.dcloud.net.cn/plugin?id=3499)
+
+- 也可以选择通过 `npm` / `yarn` 安装
+
+```shell
+# npm 安装:
+npm install @lucky-canvas/uni
+
+# yarn 安装:
+yarn add @lucky-canvas/uni
+```
+
+<br />
+
+### 2. 引入并使用
+
+```html
+<view>
+  <!-- 大转盘抽奖 -->
+  <LuckyWheel
+    width="600rpx"
+    height="600rpx"
+    ...你的配置
+  />
+  <!-- 九宫格抽奖 -->
+  <LuckyGrid
+    width="600rpx"
+    height="600rpx"
+    ...你的配置
+  />
+</view>
+```
+
+```js
+// npm 下载会默认到 node_modules 里面,直接引入包名即可
+import LuckyWheel from '@lucky-canvas/uni/lucky-wheel' // 大转盘
+import LuckyGrid from '@lucky-canvas/uni/lucky-grid' // 九宫格
+
+// 如果你是通过 HBuilderX 导入插件,那你需要指定一下路径
+// import LuckyWheel from '@/components/@lucky-canvas/uni/lucky-wheel' // 大转盘
+// import LuckyGrid from '@/components/@lucky-canvas/uni/lucky-grid' // 九宫格
+
+export default {
+  // 注册组件
+  components: { LuckyWheel, LuckyGrid },
+}
+```
+
+<br />
+
+### 3. 我提供了一个最基本的 demo 供你用于尝试
+
+由于 uni-app 渲染 md 的时候会出问题,所以我把 demo 代码放到了文档里
+
+- [https://100px.net/document/uni-app.html](https://100px.net/document/uni-app.html)
+
+<br />
+
+### **4. 补充说明**
+
+- [**如果用着顺手, 可以在 Github 上面点个 <img height="22" align="top" src="https://img.shields.io/github/stars/buuing/lucky-canvas" /> 支持一下(●'◡'●)**](https://github.com/buuing/lucky-canvas)
+
+- 另外: 如果你修复了某些bug或兼容, 欢迎提给我, 我会把你展示到官网的贡献者列表当中
+
+
+<br />
+
+### 5. 常见问题
+
+1. 转盘层级太高了, 我的弹窗盖不住怎么办?
+
+> 答: 因为小程序里canvas是原生组件顶层渲染, 我无法控制canvas的层级, 如果你想盖住它也肯简单, 你可以百度搜索`<cover>`组件
+
+2. 你这些素材, 图片组件从哪下载?
+
+> 答: 官网里的任何图片素材, 所使用到的图片资源均为学习交流使用, 请勿将其用于商业用途, 由此产生的任何商业纠纷我这边概不负责
+
+3. xxx属性怎么使用? xxx方法怎么调用?
+
+> 答: 自己去看文档, 不然难道要我把代码给你写好吗?
+
+4. 这个属性的效果与官网的描述不一致?
+
+> 答: 可能有bug, 你可以去github上的issues去提问 (请认真填写模板)
+
+5. 为什么这个插件不支持app和其他小程序
+
+> 答: 没时间, 但是希望志同道合的同学来一起参与uniapp的兼容开发
+
+---
+
+<font color="blue">作者留言: 为了使我自己保持心情愉悦, 低于5星的提问我用浏览器插件都屏蔽了</font>

+ 317 - 0
components/@lucky-canvas/uni/lucky-grid.vue

@@ -0,0 +1,317 @@
+<template>
+  <view v-if="isShow" class="lucky-box" :style="{ width: boxWidth + 'px', height: boxHeight + 'px' }">
+    <canvas
+      type="2d"
+      id="lucky-grid"
+      canvas-id="lucky-grid"
+      :style="{ width: boxWidth + 'px', height: boxHeight + 'px' }"
+    ></canvas>
+    <image
+      v-if="imgSrc"
+      :src="imgSrc"
+      @load="myLucky.clearCanvas()"
+      :style="{ width: boxWidth + 'px', height: boxHeight + 'px' }"
+    ></image>
+    <!-- #ifdef APP-PLUS -->
+    <view v-if="btnShow">
+      <view class="lucky-grid-btn" v-for="(btn, index) in btns" :key="index" @click="toPlay(btn, index)" :style="{
+        top: btn.top + 'px',
+        left: btn.left + 'px',
+        width: btn.width + 'px',
+        height: btn.height + 'px',
+      }"></view>
+    </view>
+    <!-- #endif -->
+    <!-- #ifndef APP-PLUS -->
+    <view v-if="btnShow">
+      <cover-view class="lucky-grid-btn" v-for="(btn, index) in btns" :key="index" @click="toPlay(btn, index)" :style="{
+        top: btn.top + 'px',
+        left: btn.left + 'px',
+        width: btn.width + 'px',
+        height: btn.height + 'px',
+      }"></cover-view>
+    </view>
+    <!-- #endif -->
+    <!-- #ifndef H5 -->
+    <view v-if="myLucky">
+      <div class="lucky-imgs">
+        <div v-for="(block, index) in blocks" :key="index">
+          <div v-if="block.imgs">
+            <div v-for="(img, i) in block.imgs" :key="i">
+              <image :src="img.src" :data-index="index" :data-i="i" @load="e => imgBindload(e, 'blocks')"></image>
+              <image :src="img.activeSrc" :data-index="index" :data-i="i" @load="e => imgBindloadActive(e, 'blocks')"></image>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="lucky-imgs">
+        <div v-for="(prize, index) in prizes" :key="index">
+          <div v-if="prize.imgs">
+            <div v-for="(img, i) in prize.imgs" :key="i">
+              <image :src="img.src" :data-index="index" :data-i="i" @load="e => imgBindload(e, 'prizes')"></image>
+              <image :src="img.activeSrc" :data-index="index" :data-i="i" @load="e => imgBindloadActive(e, 'prizes')"></image>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="lucky-imgs">
+        <div v-for="(btn, index) in buttons" :key="index">
+          <div v-if="btn.imgs">
+            <image v-for="(img, i) in btn.imgs" :key="i" :src="img.src" :data-index="index" :data-i="i" @load="e => imgBindload(e, 'buttons')"></image>
+          </div>
+        </div>
+      </div>
+      <div class="lucky-imgs">
+        <span v-if="button && button.imgs">
+          <image v-for="(img, i) in button.imgs" :key="i" :src="img.src" :data-i="i" @load="e => imgBindloadBtn(e, 'button')"></image>
+        </span>
+      </div>
+    </view>
+    <!-- #endif -->
+  </view>
+</template>
+
+<script>
+  import { changeUnits, resolveImage, getImage } from './utils.js'
+  import { LuckyGrid } from '../../lucky-canvas'
+  export default {
+    name: 'lucky-grid',
+    data () {
+      return {
+        imgSrc: '',
+        myLucky: null,
+        canvas: null,
+        isShow: false,
+        boxWidth: 100,
+        boxHeight: 100,
+        dpr: 1,
+        btns: [],
+        btnShow: false,
+      }
+    },
+    props: {
+      width: {
+        type: String,
+        default: '600rpx'
+      },
+      height: {
+        type: String,
+        default: '600rpx'
+      },
+      cols: {
+        type: [String, Number],
+        default: 3,
+      },
+      rows: {
+        type: [String, Number],
+        default: 3,
+      },
+      blocks: {
+        type: Array,
+        default: () => []
+      },
+      prizes: {
+        type: Array,
+        default: () => []
+      },
+      buttons: {
+        type: Array,
+        default: () => []
+      },
+      button: {
+        type: Object,
+        default: undefined
+      },
+      defaultConfig: {
+        type: Object,
+        default: () => ({})
+      },
+      defaultStyle: {
+        type: Object,
+        default: () => ({})
+      },
+      activeStyle: {
+        type: Object,
+        default: () => ({})
+      }
+    },
+    mounted () {
+      // #ifdef APP-PLUS
+      console.error('该抽奖插件的最新版暂不支持app端, 请通过npm安装旧版本【npm i uni-luck-draw@1.3.9】')
+      // #endif
+      // #ifndef APP-PLUS
+      this.initLucky()
+      // #endif
+    },
+    watch: {
+      cols (newData) {
+        this.myLucky && (this.myLucky.cols = newData)
+      },
+      rows (newData) {
+        this.myLucky && (this.myLucky.rows = newData)
+      },
+      blocks (newData) {
+        this.myLucky && (this.myLucky.blocks = newData)
+      },
+      prizes (newData) {
+        this.myLucky && (this.myLucky.prizes = newData)
+      },
+      buttons (newData) {
+        this.myLucky && (this.myLucky.buttons = newData)
+      },
+      button (newData) {
+        this.myLucky && (this.myLucky.button = newData)
+      },
+      defaultStyle (newData) {
+        this.myLucky && (this.myLucky.defaultStyle = newData)
+      },
+      defaultConfig (newData) {
+        this.myLucky && (this.myLucky.defaultConfig = newData)
+      },
+      activeStyle (newData) {
+        this.myLucky && (this.myLucky.activeStyle = newData)
+      },
+    },
+    methods: {
+      async imgBindload (res, name) {
+        const { index, i } = res.currentTarget.dataset
+        const img = this[name][index].imgs[i]
+        resolveImage(img, this.canvas)
+      },
+      async imgBindloadActive (res, name) {
+        const { index, i } = res.currentTarget.dataset
+        const img = this[name][index].imgs[i]
+        resolveImage(img, this.canvas, 'activeSrc', '$activeResolve')
+      },
+      async imgBindloadBtn (res, name) {
+        const { i } = res.currentTarget.dataset
+        const img = this[name].imgs[i]
+        resolveImage(img, this.canvas)
+      },
+      getImage () {
+        return getImage.call(this, 'lucky-grid', this.canvas)
+      },
+      hideCanvas () {
+        // #ifdef MP
+        this.getImage().then(res => {
+          this.imgSrc = res.tempFilePath
+        })
+        // #endif
+      },
+      initLucky () {
+        this.boxWidth = changeUnits(this.width)
+        this.boxHeight = changeUnits(this.height)
+        this.isShow = true
+        // 某些情况下获取不到 canvas
+        this.$nextTick(() => {
+          setTimeout(() => {
+            this.draw()
+          })
+        })
+      },
+      draw () {
+        const _this = this
+        uni.createSelectorQuery().in(this).select('#lucky-grid').fields({
+          node: true, size: true
+        }).exec((res) => {
+          // #ifdef H5
+          res[0].node = document.querySelector('#lucky-grid canvas')
+          // #endif
+          if (!res[0] || !res[0].node) return console.error('lucky-canvas 获取不到 canvas 标签')
+          const { node, width, height } = res[0]
+          const canvas = this.canvas = node
+          const ctx = this.ctx = canvas.getContext('2d')
+          const dpr = this.dpr = uni.getSystemInfoSync().pixelRatio
+          // #ifndef H5
+          canvas.width = width * dpr
+          canvas.height = height * dpr
+          ctx.scale(dpr, dpr)
+          // #endif
+          const myLucky = this.myLucky = new LuckyGrid({
+            // #ifdef H5
+            flag: 'WEB',
+            // #endif
+            // #ifdef MP
+            flag: 'MP-WX',
+            // #endif
+            ctx,
+            dpr,
+            setTimeout,
+            clearTimeout,
+            setInterval,
+            clearInterval,
+            // #ifdef H5
+            rAF: requestAnimationFrame,
+            // #endif
+            unitFunc: (num, unit) => changeUnits(num + unit),
+            afterInit: function () {
+              [..._this.$props.buttons, _this.$props.button].forEach((btn, index) => {
+                if (!btn) return
+                const [left, top, width, height] = this.getGeometricProperty([
+                  btn.x,
+                  btn.y,
+                  btn.col || 1,
+                  btn.row || 1
+                ])
+                _this.btns[index] = { top, left, width, height }
+              })
+              _this.$forceUpdate()
+            },
+            afterStart: () => {
+              this.imgSrc = ''
+            },
+          }, {
+            ...this.$props,
+            width,
+            height,
+            start: (...rest) => {
+              this.$emit('start', ...rest)
+            },
+            end: (...rest) => {
+              this.$emit('end', ...rest)
+              this.hideCanvas()
+            },
+          })
+          this.btnShow = true
+        })
+      },
+      toPlay (btn, index) {
+        this.myLucky.startCallback(btn, this.$props.buttons[index])
+      },
+      init () {
+        this.myLucky.init()
+      },
+      play (...rest) {
+        this.myLucky.play(...rest)
+      },
+      stop (...rest) {
+        this.myLucky.stop(...rest)
+      },
+    },
+  }
+</script>
+
+<style scoped>
+  .lucky-box {
+    position: relative;
+    overflow: hidden;
+    margin: 0 auto;
+  }
+  .lucky-box canvas {
+    position: absolute;
+    pointer-events: none;
+    left: 0;
+    top: 0;
+  }
+  .lucky-grid-btn {
+    position: absolute;
+    background: rgba(0, 0, 0, 0);
+    border-radius: 0;
+    cursor: pointer;
+  }
+  .lucky-imgs {
+    width: 0;
+    height: 0;
+    visibility: hidden;
+  }
+</style>

+ 255 - 0
components/@lucky-canvas/uni/lucky-wheel.vue

@@ -0,0 +1,255 @@
+<template>
+  <view v-if="isShow" class="lucky-box" :style="{ width: boxWidth + 'px', height: boxHeight + 'px' }">
+    <canvas
+      type="2d"
+      id="lucky-wheel"
+      canvas-id="lucky-wheel"
+      :style="{ width: boxWidth + 'px', height: boxHeight + 'px' }"
+    ></canvas>
+    <image
+      v-if="imgSrc"
+      :src="imgSrc"
+      @load="myLucky.clearCanvas()"
+      :style="{ width: boxWidth + 'px', height: boxHeight + 'px' }"
+    ></image>
+    <!-- #ifdef APP-PLUS -->
+    <view class="lucky-wheel-btn" @click="toPlay" :style="{ width: btnWidth + 'px', height: btnHeight + 'px' }"></view>
+    <!-- #endif -->
+    <!-- #ifndef APP-PLUS -->
+    <cover-view class="lucky-wheel-btn" @click="toPlay" :style="{ width: btnWidth + 'px', height: btnHeight + 'px' }"></cover-view>
+    <!-- #endif -->
+    <!-- #ifndef H5 -->
+    <view v-if="myLucky">
+      <div class="lucky-imgs">
+        <div v-for="(block, index) in blocks" :key="index">
+          <div v-if="block.imgs">
+            <image v-for="(img, i) in block.imgs" :key="i" :src="img.src" @load="e => imgBindload(e, 'blocks', index, i)"></image>
+          </div>
+        </div>
+      </div>
+      <div class="lucky-imgs">
+        <div v-for="(prize, index) in prizes" :key="index">
+          <div v-if="prize.imgs">
+            <image v-for="(img, i) in prize.imgs" :key="i" :src="img.src" @load="e => imgBindload(e, 'prizes', index, i)"></image>
+          </div>
+        </div>
+      </div>
+      <div class="lucky-imgs">
+        <div v-for="(btn, index) in buttons" :key="index">
+          <div v-if="btn.imgs">
+            <image v-for="(img, i) in btn.imgs" :key="i" :src="img.src" @load="e => imgBindload(e, 'buttons', index, i)"></image>
+          </div>
+        </div>
+      </div>
+    </view>
+    <!-- #endif -->
+  </view>
+</template>
+
+<script>
+  import { changeUnits, resolveImage, getImage } from './utils.js'
+  import { LuckyWheel } from '../../lucky-canvas'
+  export default {
+    name: 'lucky-wheel',
+    data () {
+      return {
+        imgSrc: '',
+        myLucky: null,
+        canvas: null,
+        isShow: false,
+        boxWidth: 100,
+        boxHeight: 100,
+        btnWidth: 0,
+        btnHeight: 0,
+        dpr: 1,
+      }
+    },
+    props: {
+      width: {
+        type: String,
+        default: '600rpx'
+      },
+      height: {
+        type: String,
+        default: '600rpx'
+      },
+      blocks: {
+        type: Array,
+        default: () => []
+      },
+      prizes: {
+        type: Array,
+        default: () => []
+      },
+      buttons: {
+        type: Array,
+        default: () => []
+      },
+      defaultConfig: {
+        type: Object,
+        default: () => ({})
+      },
+      defaultStyle: {
+        type: Object,
+        default: () => ({})
+      },
+    },
+    mounted () {
+      // #ifdef APP-PLUS
+      console.error('该抽奖插件的最新版暂不支持app端, 请通过npm安装旧版本【npm i uni-luck-draw@1.3.9】')
+      // #endif
+      // #ifndef APP-PLUS
+      this.initLucky()
+      // #endif
+    },
+    watch: {
+      blocks (newData) {
+        this.myLucky && (this.myLucky.blocks = newData)
+      },
+      prizes (newData) {
+        this.myLucky && (this.myLucky.prizes = newData)
+      },
+      buttons (newData) {
+        this.myLucky && (this.myLucky.buttons = newData)
+      },
+      defaultStyle (newData) {
+        this.myLucky && (this.myLucky.defaultStyle = newData)
+      },
+      defaultConfig (newData) {
+        this.myLucky && (this.myLucky.defaultConfig = newData)
+      },
+    },
+    methods: {
+      async imgBindload (res, name, index, i) {
+        const img = this[name][index].imgs[i]
+        resolveImage(img, this.canvas)
+      },
+      getImage () {
+        return getImage.call(this, 'lucky-wheel', this.canvas)
+      },
+      hideCanvas () {
+        // #ifdef MP
+        this.getImage().then(res => {
+          this.imgSrc = res.tempFilePath
+        })
+        // #endif
+      },
+      initLucky () {
+        this.boxWidth = changeUnits(this.width)
+        this.boxHeight = changeUnits(this.height)
+        this.isShow = true
+        // 某些情况下获取不到 canvas
+        this.$nextTick(() => {
+          setTimeout(() => {
+            this.draw()
+          })
+        })
+      },
+      draw () {
+        const _this = this
+        uni.createSelectorQuery().in(this).select('#lucky-wheel').fields({
+          node: true, size: true
+        }).exec((res) => {
+          // #ifdef H5
+          res[0].node = document.querySelector('#lucky-wheel canvas')
+          // #endif
+          if (!res[0] || !res[0].node) return console.error('lucky-canvas 获取不到 canvas 标签')
+          const { node, width, height } = res[0]
+          const canvas = this.canvas = node
+          const ctx = this.ctx = canvas.getContext('2d')
+          const dpr = this.dpr = uni.getSystemInfoSync().pixelRatio
+          // #ifndef H5
+          canvas.width = width * dpr
+          canvas.height = height * dpr
+          ctx.scale(dpr, dpr)
+          // #endif
+          const Radius = Math.min(width, height) / 2
+          const myLucky = this.myLucky = new LuckyWheel({
+            // #ifdef H5
+            flag: 'WEB',
+            // #endif
+            // #ifdef MP
+            flag: 'MP-WX',
+            // #endif
+            ctx,
+            dpr,
+            setTimeout,
+            clearTimeout,
+            setInterval,
+            clearInterval,
+            // #ifdef H5
+            rAF: requestAnimationFrame,
+            // #endif
+            unitFunc: (num, unit) => changeUnits(num + unit),
+            beforeCreate: function () {
+              ctx.translate(Radius, Radius)
+            },
+            beforeResize: function () {
+              ctx.translate(-Radius, -Radius)
+            },
+            afterInit: function () {
+              // 动态设置按钮
+              _this.btnWidth = this.maxBtnRadius * 2
+              _this.btnHeight = this.maxBtnRadius * 2
+              _this.$forceUpdate()
+            },
+            afterStart: () => {
+              this.imgSrc = ''
+            },
+          }, {
+            ...this.$props,
+            width,
+            height,
+            start: (...rest) => {
+              this.$emit('start', ...rest)
+            },
+            end: (...rest) => {
+              this.$emit('end', ...rest)
+              this.hideCanvas()
+            },
+          })
+        })
+      },
+      toPlay (e) {
+        this.myLucky.startCallback()
+      },
+      init () {
+        this.myLucky.init()
+      },
+      play (...rest) {
+        this.myLucky.play(...rest)
+      },
+      stop (...rest) {
+        this.myLucky.stop(...rest)
+      },
+    },
+  }
+</script>
+
+<style scoped>
+  .lucky-box {
+    position: relative;
+    overflow: hidden;
+    margin: 0 auto;
+  }
+  .lucky-box canvas {
+    position: absolute;
+    pointer-events: none;
+    left: 0;
+    top: 0;
+  }
+  .lucky-wheel-btn {
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    transform: translate(-50%, -50%);
+    background: rgba(0, 0, 0, 0);
+    border-radius: 50%;
+    cursor: pointer;
+  }
+  .lucky-imgs {
+    width: 0;
+    height: 0;
+    visibility: hidden;
+  }
+</style>

+ 23 - 0
components/@lucky-canvas/uni/package.json

@@ -0,0 +1,23 @@
+{
+  "name": "@lucky-canvas/uni",
+  "version": "0.0.10",
+  "description": "uni-app【大转盘 / 九宫格 / 老虎机】抽奖插件",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "keywords": [
+    "uni-app抽奖"
+  ],
+  "files": [
+    "lucky-wheel.vue",
+    "lucky-grid.vue",
+    "slot-machine.vue",
+    "utils.js",
+    "demo.vue"
+  ],
+  "author": "ldq <ldq404@qq.com>",
+  "license": "Apache-2.0",
+  "dependencies": {
+    "lucky-canvas": "~1.7.19"
+  }
+}

+ 214 - 0
components/@lucky-canvas/uni/slot-machine.vue

@@ -0,0 +1,214 @@
+<template>
+  <view v-if="isShow" class="lucky-box" :style="{ width: boxWidth + 'px', height: boxHeight + 'px' }">
+    <canvas
+      type="2d"
+      id="slot-machine"
+      canvas-id="slot-machine"
+      :style="{ width: boxWidth + 'px', height: boxHeight + 'px' }"
+    ></canvas>
+    <image
+      v-if="imgSrc"
+      :src="imgSrc"
+      @load="myLucky.clearCanvas()"
+      :style="{ width: boxWidth + 'px', height: boxHeight + 'px' }"
+    ></image>
+    <!-- #ifndef H5 -->
+    <view v-if="myLucky">
+      <div class="lucky-imgs">
+        <div v-for="(block, index) in blocks" :key="index">
+          <div v-if="block.imgs">
+            <image v-for="(img, i) in block.imgs" :key="i" :src="img.src" @load="e => imgBindload(e, 'blocks', index, i)"></image>
+          </div>
+        </div>
+      </div>
+      <div class="lucky-imgs">
+        <div v-for="(prize, index) in prizes" :key="index">
+          <div v-if="prize.imgs">
+            <image v-for="(img, i) in prize.imgs" :key="i" :src="img.src" @load="e => imgBindload(e, 'prizes', index, i)"></image>
+          </div>
+        </div>
+      </div>
+    </view>
+    <!-- #endif -->
+  </view>
+</template>
+
+<script>
+  import { changeUnits, resolveImage, getImage } from './utils.js'
+  import { SlotMachine } from '../../lucky-canvas'
+  export default {
+    name: 'slot-machine',
+    data () {
+      return {
+        imgSrc: '',
+        myLucky: null,
+        canvas: null,
+        isShow: false,
+        boxWidth: 100,
+        boxHeight: 100,
+        btnWidth: 0,
+        btnHeight: 0,
+        dpr: 1,
+      }
+    },
+    props: {
+      width: {
+        type: String,
+        default: '600rpx'
+      },
+      height: {
+        type: String,
+        default: '600rpx'
+      },
+      blocks: {
+        type: Array,
+        default: () => []
+      },
+      prizes: {
+        type: Array,
+        default: () => []
+      },
+      slots: {
+        type: Array,
+        default: () => []
+      },
+      defaultConfig: {
+        type: Object,
+        default: () => ({})
+      },
+      defaultStyle: {
+        type: Object,
+        default: () => ({})
+      },
+    },
+    mounted () {
+      // #ifndef APP-PLUS
+      this.initLucky()
+      // #endif
+    },
+    watch: {
+      blocks (newData) {
+        this.myLucky && (this.myLucky.blocks = newData)
+      },
+      prizes (newData) {
+        this.myLucky && (this.myLucky.prizes = newData)
+      },
+      slots (newData) {
+        this.myLucky && (this.myLucky.slots = newData)
+      },
+      defaultStyle (newData) {
+        this.myLucky && (this.myLucky.defaultStyle = newData)
+      },
+      defaultConfig (newData) {
+        this.myLucky && (this.myLucky.defaultConfig = newData)
+      },
+    },
+    methods: {
+      async imgBindload (res, name, index, i) {
+        const img = this[name][index].imgs[i]
+        resolveImage(img, this.canvas)
+      },
+      getImage () {
+        return getImage.call(this, 'slot-machine', this.canvas)
+      },
+      hideCanvas () {
+        // #ifdef MP
+        this.getImage().then(res => {
+          this.imgSrc = res.tempFilePath
+        })
+        // #endif
+      },
+      initLucky () {
+        this.boxWidth = changeUnits(this.width)
+        this.boxHeight = changeUnits(this.height)
+        this.isShow = true
+        // 某些情况下获取不到 canvas
+        this.$nextTick(() => {
+          setTimeout(() => {
+            this.draw()
+          })
+        })
+      },
+      draw () {
+        const _this = this
+        uni.createSelectorQuery().in(this).select('#slot-machine').fields({
+          node: true, size: true
+        }).exec((res) => {
+          // #ifdef H5
+          res[0].node = document.querySelector('#slot-machine canvas')
+          // #endif
+          if (!res[0] || !res[0].node) return console.error('lucky-canvas 获取不到 canvas 标签')
+          const { node, width, height } = res[0]
+          const canvas = this.canvas = node
+          const ctx = this.ctx = canvas.getContext('2d')
+          const dpr = this.dpr = uni.getSystemInfoSync().pixelRatio
+          // #ifndef H5
+          canvas.width = width * dpr
+          canvas.height = height * dpr
+          ctx.scale(dpr, dpr)
+          // #endif
+          const myLucky = this.myLucky = new SlotMachine({
+            // #ifdef H5
+            flag: 'WEB',
+            // #endif
+            // #ifdef MP
+            flag: 'MP-WX',
+            // #endif
+            ctx,
+            dpr,
+            // #ifndef H5
+            offscreenCanvas: uni.createOffscreenCanvas({ type: '2d' }),
+            // #endif
+            setTimeout,
+            clearTimeout,
+            setInterval,
+            clearInterval,
+            // #ifdef H5
+            rAF: requestAnimationFrame,
+            // #endif
+            unitFunc: (num, unit) => changeUnits(num + unit),
+            afterStart: () => {
+              this.imgSrc = ''
+            },
+          }, {
+            ...this.$props,
+            width,
+            height,
+            end: (...rest) => {
+              this.$emit('end', ...rest)
+              this.hideCanvas()
+            },
+          })
+        })
+      },
+      init () {
+        this.myLucky.init()
+      },
+      play (...rest) {
+        this.myLucky.play(...rest)
+      },
+      stop (...rest) {
+        this.myLucky.stop(...rest)
+      },
+    },
+  }
+</script>
+
+<style scoped>
+  .lucky-box {
+    position: relative;
+    overflow: hidden;
+    margin: 0 auto;
+  }
+  .lucky-box canvas {
+    position: absolute;
+    pointer-events: none;
+    left: 0;
+    top: 0;
+  }
+  .lucky-imgs {
+    width: 0;
+    height: 0;
+    visibility: hidden;
+  }
+</style>

+ 82 - 0
components/@lucky-canvas/uni/utils.js

@@ -0,0 +1,82 @@
+let windowWidth = uni.getSystemInfoSync().windowWidth
+// uni-app@2.9起, 屏幕最多适配到960, 超出则按375计算
+if (windowWidth > 960) windowWidth = 375
+
+export const rpx2px = (value) => {
+  if (typeof value === 'string') value = Number(value.replace(/[a-z]*/g, ''))
+  return windowWidth / 750 * value
+}
+
+export const changeUnits = (value) => {
+  return Number(value.replace(/^(\-*[0-9.]*)([a-z%]*)$/, (value, num, unit) => {
+    switch (unit) {
+      case 'px':
+        num *= 1
+        break
+      case 'rpx':
+        num = rpx2px(num)
+        break
+      default:
+        num *= 1
+        break
+    }
+    return num
+  }))
+}
+
+export const resolveImage = async (img, canvas, srcName = 'src', resolveName = '$resolve') => {
+  let imgObj
+  // 区分 H5 和小程序
+  if (window) {
+    imgObj = new Image()
+  } else {
+    imgObj = canvas.createImage()
+  }
+  // 成功回调
+  imgObj.onload = () => {
+    img[resolveName](imgObj)
+  }
+  // 失败回调
+  imgObj.onerror = (err) => {
+    console.error(err)
+    // img['$reject']()
+  }
+  // 设置src
+  imgObj.src = img[srcName]
+}
+
+// 旧版canvas引入图片的方法
+// export const resolveImage = async (res, img, imgName = 'src', resolveName = '$resolve') => {
+//   const src = img[imgName]
+//   const $resolve = img[resolveName]
+//   // #ifdef MP
+//   // 如果是base64就调用base64src()方法把图片写入本地, 然后渲染临时路径
+//   if (/^data:image\/([a-z]+);base64,/.test(src)) {
+//     const path = await base64src(src)
+//     $resolve({ ...res.detail, path })
+//     return
+//   }
+//   // #endif
+//   // 如果是本地图片, 直接返回
+//   if (src.indexOf('http') !== 0) {
+//     $resolve({ ...res.detail, path:src })
+//     return
+//   }
+//   // 如果是网络图片, 则通过getImageInfo()方法获取图片宽高
+//   uni.getImageInfo({
+//     src: src,
+//     success: (imgObj) => $resolve(imgObj),
+//     fail: () => console.error('API `uni.getImageInfo` 加载图片失败', src)
+//   })
+// }
+
+export function getImage(canvasId, canvas) {
+  return new Promise((resolve, reject) => {
+    uni.canvasToTempFilePath({
+      canvas,
+      canvasId,
+      success: res => resolve(res),
+      fail: err => reject(err)
+    }, this)
+  })
+}

+ 3 - 2
components/My_listbox.vue

@@ -111,11 +111,12 @@ export default {
             })
         },
         /* 分页 */
-        paging(content, res) {
+        paging(data, res, update = false) {
+            let content = JSON.parse(JSON.stringify(data))
             content.pageNumber = res.pageNumber + 1;
             content.pageTotal = res.pageTotal;
             // this.pagingText = content.pageNumber + ' / ' + content.pageTotal;
-            this.bottomTips = res.total != 0 && content.pageNumber >= content.pageTotal;
+            if (!update) this.bottomTips = res.total != 0 && content.pageNumber >= content.pageTotal;
             if (this.isShowEmpty) this.empty = res.total == 0;
             return content;
         }

+ 201 - 0
components/lucky-canvas/LICENSE

@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [2021] [Li Dong Qi]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 42 - 0
components/lucky-canvas/README.md

@@ -0,0 +1,42 @@
+
+
+<div align="center">
+  <img src="https://unpkg.com/buuing@0.0.1/imgs/lucky-canvas.png" width="128" alt="logo" />
+  <h1>lucky-canvas 抽奖插件</h1>
+  <p>一个基于 JavaScript 的跨平台 ( 大转盘 / 九宫格 / 老虎机 ) 抽奖插件</p>
+  <p>
+    <a href="https://github.com/buuing/lucky-canvas/stargazers" target="_black">
+      <img src="https://img.shields.io/github/stars/buuing/lucky-canvas?color=%23ffba15&logo=github&style=flat-square" alt="stars" />
+    </a>
+    <a href="https://github.com/buuing/lucky-canvas/network/members" target="_black">
+      <img src="https://img.shields.io/github/forks/buuing/lucky-canvas?color=%23ffba15&logo=github&style=flat-square" alt="forks" />
+    </a>
+    <a href="https://github.com/buuing" target="_black">
+      <img src="https://img.shields.io/badge/Author-%20buuing%20-7289da.svg?&logo=github&style=flat-square" alt="author" />
+    </a>
+    <a href="https://github.com/buuing/lucky-canvas/blob/master/LICENSE" target="_black">
+      <img src="https://img.shields.io/github/license/buuing/lucky-canvas?color=%232dce89&logo=github&style=flat-square" alt="license" />
+    </a>
+  </p>
+</div>
+
+<br />
+
+## 官方文档 & Demo演示
+
+> **中文**:[https://100px.net/usage/js.html](https://100px.net/usage/js.html)  
+
+> **English**:**If anyone can help translate the document, please contact me** `ldq404@qq.com`
+
+
+<br />
+
+## 在 JS / TS 中使用
+
+- [跳转官网 查看详情](https://100px.net/usage/js.html)
+
+<br />
+
+## 🙏🙏🙏 点个Star
+
+**如果您觉得这个项目还不错, 可以在 [Github](https://github.com/buuing/lucky-canvas) 上面帮我点个`star`, 支持一下作者 ☜(゚ヮ゚☜)**

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 15 - 0
components/lucky-canvas/dist/index.cjs.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
components/lucky-canvas/dist/index.cjs.js.map


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 14 - 0
components/lucky-canvas/dist/index.esm.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
components/lucky-canvas/dist/index.esm.js.map


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 14 - 0
components/lucky-canvas/dist/index.umd.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 0 - 0
components/lucky-canvas/dist/index.umd.js.map


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 14 - 0
components/lucky-canvas/dist/lucky-canvas.js


+ 1 - 0
components/lucky-canvas/index.js

@@ -0,0 +1 @@
+module.exports = require('./dist/index.umd.js')

+ 66 - 0
components/lucky-canvas/package.json

@@ -0,0 +1,66 @@
+{
+  "name": "lucky-canvas",
+  "version": "1.7.26",
+  "description": "一个基于原生 js 的(大转盘 / 九宫格 / 老虎机)抽奖插件",
+  "main": "dist/index.cjs.js",
+  "module": "dist/index.esm.js",
+  "unpkg": "dist/index.umd.js",
+  "jsdelivr": "dist/index.umd.js",
+  "types": "types/index.d.ts",
+  "scripts": {
+    "dev": "rollup --config rollup.config.dev.js -w",
+    "build": "rollup --config rollup.config.build.js"
+  },
+  "homepage": "https://100px.net",
+  "bugs": "https://github.com/LuckDraw/lucky-canvas/issues",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/LuckDraw/lucky-canvas.git",
+    "directory": "packages/lucky-canvas"
+  },
+  "author": "ldq <ldq404@qq.com>",
+  "license": "Apache-2.0",
+  "files": [
+    "dist",
+    "types",
+    "index.js"
+  ],
+  "keywords": [
+    "大转盘抽奖",
+    "九宫格抽奖",
+    "老虎机抽奖",
+    "抽奖插件",
+    "js抽奖",
+    "移动端抽奖",
+    "canvas抽奖"
+  ],
+  "devDependencies": {
+    "@babel/core": "^7.12.3",
+    "@babel/preset-env": "^7.12.1",
+    "@babel/plugin-transform-runtime": "^7.16.4",
+    "@babel/runtime": "^7.16.3",
+    "core-js": "^3.19.2",
+    "@rollup/plugin-commonjs": "^16.0.0",
+    "@rollup/plugin-eslint": "^8.0.1",
+    "@rollup/plugin-json": "^4.1.0",
+    "@rollup/plugin-node-resolve": "^10.0.0",
+    "@rollup/plugin-typescript": "^6.1.0",
+    "@typescript-eslint/parser": "^4.14.0",
+    "babel-plugin-external-helpers": "^6.22.0",
+    "babel-preset-latest": "^6.24.1",
+    "eslint": "^7.18.0",
+    "eslint-plugin-prettier": "^3.3.1",
+    "prettier": "^2.2.1",
+    "rollup": "^2.33.1",
+    "rollup-plugin-babel": "^4.4.0",
+    "rollup-plugin-livereload": "^2.0.0",
+    "rollup-plugin-serve": "^1.1.0",
+    "rollup-plugin-terser": "^7.0.2",
+    "rollup-plugin-delete": "^2.0.0",
+    "rollup-plugin-dts": "^3.0.2",
+    "rollup-plugin-typescript2": "^0.30.0",
+    "tslib": "^2.3.1",
+    "typescript": "^4.0.5"
+  },
+  "dependencies": {}
+}

+ 752 - 0
components/lucky-canvas/types/index.d.ts

@@ -0,0 +1,752 @@
+declare type FontItemType = {
+    text: string;
+    top?: string | number;
+    left?: string | number;
+    fontColor?: string;
+    fontSize?: string;
+    fontStyle?: string;
+    fontWeight?: string;
+    lineHeight?: string;
+};
+declare type FontExtendType = {
+    wordWrap?: boolean;
+    lengthLimit?: string | number;
+    lineClamp?: number;
+};
+declare type ImgType = HTMLImageElement | HTMLCanvasElement;
+declare type ImgItemType = {
+    src: string;
+    top?: string | number;
+    left?: string | number;
+    width?: string;
+    height?: string;
+    formatter?: (img: ImgType) => ImgType;
+    $resolve?: Function;
+    $reject?: Function;
+};
+declare type BorderRadiusType = string | number;
+declare type BackgroundType = string;
+declare type ShadowType = string;
+declare type ConfigType = {
+    nodeType?: number;
+    flag: 'WEB' | 'MP-WX' | 'UNI-H5' | 'UNI-MP' | 'TARO-H5' | 'TARO-MP';
+    el?: string;
+    divElement?: HTMLDivElement;
+    canvasElement?: HTMLCanvasElement;
+    ctx: CanvasRenderingContext2D;
+    dpr: number;
+    handleCssUnit?: (num: number, unit: string) => number;
+    rAF?: Function;
+    setTimeout: Function;
+    setInterval: Function;
+    clearTimeout: Function;
+    clearInterval: Function;
+    beforeCreate?: Function;
+    beforeResize?: Function;
+    afterResize?: Function;
+    beforeInit?: Function;
+    afterInit?: Function;
+    beforeDraw?: Function;
+    afterDraw?: Function;
+    afterStart?: Function;
+};
+declare type RequireKey = 'width' | 'height';
+declare type UserConfigType = Partial<Omit<ConfigType, RequireKey>> & Required<Pick<ConfigType, RequireKey>>;
+declare type Tuple<T, Len extends number, Res extends T[] = []> = Res['length'] extends Len ? Res : Tuple<T, Len, [...Res, T]>;
+
+interface WatchOptType {
+    handler?: () => Function;
+    immediate?: boolean;
+    deep?: boolean;
+}
+
+declare class Lucky {
+    static version: string;
+    protected readonly version: string;
+    protected readonly config: ConfigType;
+    protected readonly ctx: CanvasRenderingContext2D;
+    protected htmlFontSize: number;
+    protected rAF: Function;
+    protected boxWidth: number;
+    protected boxHeight: number;
+    protected data: {
+        width: string | number;
+        height: string | number;
+    };
+    /**
+     * 公共构造器
+     * @param config
+     */
+    constructor(config: string | HTMLDivElement | UserConfigType, data: {
+        width: string | number;
+        height: string | number;
+    });
+    /**
+     * 初始化组件大小/单位
+     */
+    protected resize(): void;
+    /**
+     * 初始化方法
+     */
+    protected initLucky(): void;
+    /**
+     * 鼠标点击事件
+     * @param e 事件参数
+     */
+    protected handleClick(e: MouseEvent): void;
+    /**
+     * 根标签的字体大小
+     */
+    protected setHTMLFontSize(): void;
+    clearCanvas(): void;
+    /**
+     * 设备像素比
+     * window 环境下自动获取, 其余环境手动传入
+     */
+    protected setDpr(): void;
+    /**
+     * 重置盒子和canvas的宽高
+     */
+    private resetWidthAndHeight;
+    /**
+     * 根据 dpr 缩放 canvas 并处理位移
+     */
+    protected zoomCanvas(): void;
+    /**
+     * 从 window 对象上获取一些方法
+     */
+    private initWindowFunction;
+    isWeb(): boolean;
+    /**
+     * 异步加载图片并返回图片的几何信息
+     * @param src 图片路径
+     * @param info 图片信息
+     */
+    protected loadImg(src: string, info: ImgItemType, resolveName?: string): Promise<ImgType>;
+    /**
+     * 公共绘制图片的方法
+     * @param imgObj 图片对象
+     * @param rectInfo: [x轴位置, y轴位置, 渲染宽度, 渲染高度]
+     */
+    protected drawImage(ctx: CanvasRenderingContext2D, imgObj: ImgType, ...rectInfo: [...Tuple<number, 4>, ...Partial<Tuple<number, 4>>]): void;
+    /**
+     * 计算图片的渲染宽高
+     * @param imgObj 图片标签元素
+     * @param imgInfo 图片信息
+     * @param maxWidth 最大宽度
+     * @param maxHeight 最大高度
+     * @return [渲染宽度, 渲染高度]
+     */
+    protected computedWidthAndHeight(imgObj: ImgType, imgInfo: ImgItemType, maxWidth: number, maxHeight: number): [number, number];
+    /**
+     * 转换单位
+     * @param { string } value 将要转换的值
+     * @param { number } denominator 分子
+     * @return { number } 返回新的字符串
+     */
+    protected changeUnits(value: string, denominator?: number): number;
+    /**
+     * 获取长度
+     * @param length 将要转换的长度
+     * @param maxLength 最大长度
+     * @return 返回长度
+     */
+    protected getLength(length: string | number | undefined, maxLength?: number): number;
+    /**
+     * 获取相对(居中)X坐标
+     * @param width
+     * @param col
+     */
+    protected getOffsetX(width: number, maxWidth?: number): number;
+    protected getOffscreenCanvas(width: number, height: number): {
+        _offscreenCanvas: HTMLCanvasElement;
+        _ctx: CanvasRenderingContext2D;
+    } | void;
+    /**
+     * 添加一个新的响应式数据 (临时)
+     * @param data 数据
+     * @param key 属性
+     * @param value 新值
+     */
+    $set(data: object, key: string | number, value: any): void;
+    /**
+     * 添加一个属性计算 (临时)
+     * @param data 源数据
+     * @param key 属性名
+     * @param callback 回调函数
+     */
+    protected $computed(data: object, key: string, callback: Function): void;
+    /**
+     * 添加一个观察者 create user watcher
+     * @param expr 表达式
+     * @param handler 回调函数
+     * @param watchOpt 配置参数
+     * @return 卸载当前观察者的函数 (暂未返回)
+     */
+    protected $watch(expr: string | Function, handler: Function | WatchOptType, watchOpt?: WatchOptType): Function;
+}
+
+declare type PrizeFontType$2 = FontItemType & FontExtendType;
+declare type ButtonFontType$1 = FontItemType & {};
+declare type BlockImgType$2 = ImgItemType & {
+    rotate?: boolean;
+};
+declare type PrizeImgType$2 = ImgItemType & {};
+declare type ButtonImgType$1 = ImgItemType & {};
+declare type BlockType$2 = {
+    padding?: string;
+    background?: BackgroundType;
+    imgs?: Array<BlockImgType$2>;
+};
+declare type PrizeType$2 = {
+    range?: number;
+    background?: BackgroundType;
+    fonts?: Array<PrizeFontType$2>;
+    imgs?: Array<PrizeImgType$2>;
+};
+declare type ButtonType$1 = {
+    radius?: string;
+    pointer?: boolean;
+    background?: BackgroundType;
+    fonts?: Array<ButtonFontType$1>;
+    imgs?: Array<ButtonImgType$1>;
+};
+declare type DefaultConfigType$2 = {
+    gutter?: string | number;
+    offsetDegree?: number;
+    speed?: number;
+    speedFunction?: string;
+    accelerationTime?: number;
+    decelerationTime?: number;
+    stopRange?: number;
+};
+declare type DefaultStyleType$2 = {
+    background?: BackgroundType;
+    fontColor?: PrizeFontType$2['fontColor'];
+    fontSize?: PrizeFontType$2['fontSize'];
+    fontStyle?: PrizeFontType$2['fontStyle'];
+    fontWeight?: PrizeFontType$2['fontWeight'];
+    lineHeight?: PrizeFontType$2['lineHeight'];
+    wordWrap?: PrizeFontType$2['wordWrap'];
+    lengthLimit?: PrizeFontType$2['lengthLimit'];
+    lineClamp?: PrizeFontType$2['lineClamp'];
+};
+declare type StartCallbackType$1 = (e: MouseEvent) => void;
+declare type EndCallbackType$2 = (prize: object) => void;
+interface LuckyWheelConfig {
+    width: string | number;
+    height: string | number;
+    blocks?: Array<BlockType$2>;
+    prizes?: Array<PrizeType$2>;
+    buttons?: Array<ButtonType$1>;
+    defaultConfig?: DefaultConfigType$2;
+    defaultStyle?: DefaultStyleType$2;
+    start?: StartCallbackType$1;
+    end?: EndCallbackType$2;
+}
+
+declare class LuckyWheel extends Lucky {
+    private blocks;
+    private prizes;
+    private buttons;
+    private defaultConfig;
+    private defaultStyle;
+    private _defaultConfig;
+    private _defaultStyle;
+    private startCallback?;
+    private endCallback?;
+    private Radius;
+    private prizeRadius;
+    private prizeDeg;
+    private prizeAng;
+    private rotateDeg;
+    private maxBtnRadius;
+    private startTime;
+    private endTime;
+    private stopDeg;
+    private endDeg;
+    private FPS;
+    /**
+     * 游戏当前的阶段
+     * step = 0 时, 游戏尚未开始
+     * step = 1 时, 此时处于加速阶段
+     * step = 2 时, 此时处于匀速阶段
+     * step = 3 时, 此时处于减速阶段
+     */
+    private step;
+    /**
+     * 中奖索引
+     * prizeFlag = undefined 时, 处于开始抽奖阶段, 正常旋转
+     * prizeFlag >= 0 时, 说明stop方法被调用, 并且传入了中奖索引
+     * prizeFlag === -1 时, 说明stop方法被调用, 并且传入了负值, 本次抽奖无效
+     */
+    private prizeFlag;
+    private ImageCache;
+    /**
+     * 大转盘构造器
+     * @param config 配置项
+     * @param data 抽奖数据
+     */
+    constructor(config: UserConfigType, data: LuckyWheelConfig);
+    protected resize(): void;
+    protected initLucky(): void;
+    /**
+     * 初始化数据
+     * @param data
+     */
+    private initData;
+    /**
+     * 初始化属性计算
+     */
+    private initComputed;
+    /**
+     * 初始化观察者
+     */
+    private initWatch;
+    /**
+     * 初始化 canvas 抽奖
+     */
+    init(): Promise<void>;
+    private initImageCache;
+    /**
+     * canvas点击事件
+     * @param e 事件参数
+     */
+    protected handleClick(e: MouseEvent): void;
+    /**
+     * 根据索引单独加载指定图片并缓存
+     * @param cellName 模块名称
+     * @param cellIndex 模块索引
+     * @param imgName 模块对应的图片缓存
+     * @param imgIndex 图片索引
+     */
+    private loadAndCacheImg;
+    private drawBlock;
+    /**
+     * 开始绘制
+     */
+    protected draw(): void;
+    /**
+     * 刻舟求剑
+     */
+    private carveOnGunwaleOfAMovingBoat;
+    /**
+     * 对外暴露: 开始抽奖方法
+     */
+    play(): void;
+    /**
+     * 对外暴露: 缓慢停止方法
+     * @param index 中奖索引
+     */
+    stop(index?: number): void;
+    /**
+     * 实际开始执行方法
+     * @param num 记录帧动画执行多少次
+     */
+    private run;
+    /**
+     * 换算渲染坐标
+     * @param x
+     * @param y
+     */
+    protected conversionAxis(x: number, y: number): [number, number];
+}
+
+declare type PrizeFontType$1 = FontItemType & FontExtendType;
+declare type ButtonFontType = FontItemType & FontExtendType;
+declare type BlockImgType$1 = ImgItemType & {};
+declare type PrizeImgType$1 = ImgItemType & {
+    activeSrc?: string;
+};
+declare type ButtonImgType = ImgItemType & {};
+declare type BlockType$1 = {
+    borderRadius?: BorderRadiusType;
+    background?: BackgroundType;
+    padding?: string;
+    paddingTop?: string | number;
+    paddingRight?: string | number;
+    paddingBottom?: string | number;
+    paddingLeft?: string | number;
+    imgs?: Array<BlockImgType$1>;
+};
+declare type CellType<T, U> = {
+    x: number;
+    y: number;
+    col?: number;
+    row?: number;
+    borderRadius?: BorderRadiusType;
+    background?: BackgroundType;
+    shadow?: ShadowType;
+    fonts?: Array<T>;
+    imgs?: Array<U>;
+};
+declare type PrizeType$1 = CellType<PrizeFontType$1, PrizeImgType$1> & {
+    range?: number;
+    disabled?: boolean;
+};
+declare type ButtonType = CellType<ButtonFontType, ButtonImgType> & {
+    callback?: Function;
+};
+declare type DefaultConfigType$1 = {
+    gutter?: number;
+    speed?: number;
+    accelerationTime?: number;
+    decelerationTime?: number;
+};
+declare type DefaultStyleType$1 = {
+    borderRadius?: BorderRadiusType;
+    background?: BackgroundType;
+    shadow?: ShadowType;
+    fontColor?: PrizeFontType$1['fontColor'];
+    fontSize?: PrizeFontType$1['fontSize'];
+    fontStyle?: PrizeFontType$1['fontStyle'];
+    fontWeight?: PrizeFontType$1['fontWeight'];
+    lineHeight?: PrizeFontType$1['lineHeight'];
+    wordWrap?: PrizeFontType$1['wordWrap'];
+    lengthLimit?: PrizeFontType$1['lengthLimit'];
+    lineClamp?: PrizeFontType$1['lineClamp'];
+};
+declare type ActiveStyleType = {
+    background?: BackgroundType;
+    shadow?: ShadowType;
+    fontColor?: PrizeFontType$1['fontColor'];
+    fontSize?: PrizeFontType$1['fontSize'];
+    fontStyle?: PrizeFontType$1['fontStyle'];
+    fontWeight?: PrizeFontType$1['fontWeight'];
+    lineHeight?: PrizeFontType$1['lineHeight'];
+};
+declare type RowsType = number;
+declare type ColsType = number;
+declare type StartCallbackType = (e: MouseEvent, button?: ButtonType) => void;
+declare type EndCallbackType$1 = (prize: object) => void;
+interface LuckyGridConfig {
+    width: string | number;
+    height: string | number;
+    rows?: RowsType;
+    cols?: ColsType;
+    blocks?: Array<BlockType$1>;
+    prizes?: Array<PrizeType$1>;
+    buttons?: Array<ButtonType>;
+    button?: ButtonType;
+    defaultConfig?: DefaultConfigType$1;
+    defaultStyle?: DefaultStyleType$1;
+    activeStyle?: ActiveStyleType;
+    start?: StartCallbackType;
+    end?: EndCallbackType$1;
+}
+
+declare class LuckyGrid extends Lucky {
+    private rows;
+    private cols;
+    private blocks;
+    private prizes;
+    private buttons;
+    private button?;
+    private defaultConfig;
+    private defaultStyle;
+    private activeStyle;
+    private _defaultConfig;
+    private _defaultStyle;
+    private _activeStyle;
+    private startCallback?;
+    private endCallback?;
+    private cellWidth;
+    private cellHeight;
+    private startTime;
+    private endTime;
+    private currIndex;
+    private stopIndex;
+    private endIndex;
+    private demo;
+    private timer;
+    private FPS;
+    /**
+     * 游戏当前的阶段
+     * step = 0 时, 游戏尚未开始
+     * step = 1 时, 此时处于加速阶段
+     * step = 2 时, 此时处于匀速阶段
+     * step = 3 时, 此时处于减速阶段
+     */
+    private step;
+    /**
+     * 中奖索引
+     * prizeFlag = undefined 时, 处于开始抽奖阶段, 正常旋转
+     * prizeFlag >= 0 时, 说明stop方法被调用, 并且传入了中奖索引
+     * prizeFlag === -1 时, 说明stop方法被调用, 并且传入了负值, 本次抽奖无效
+     */
+    private prizeFlag;
+    private cells;
+    private prizeArea;
+    private ImageCache;
+    /**
+     * 九宫格构造器
+     * @param config 配置项
+     * @param data 抽奖数据
+     */
+    constructor(config: UserConfigType, data: LuckyGridConfig);
+    protected resize(): void;
+    protected initLucky(): void;
+    /**
+     * 初始化数据
+     * @param data
+     */
+    private initData;
+    /**
+     * 初始化属性计算
+     */
+    private initComputed;
+    /**
+     * 初始化观察者
+     */
+    private initWatch;
+    /**
+     * 初始化 canvas 抽奖
+     */
+    init(): Promise<void>;
+    private initImageCache;
+    /**
+     * canvas点击事件
+     * @param e 事件参数
+     */
+    protected handleClick(e: MouseEvent): void;
+    /**
+     * 根据索引单独加载指定图片并缓存
+     * @param cellName 模块名称
+     * @param cellIndex 模块索引
+     * @param imgName 模块对应的图片缓存
+     * @param imgIndex 图片索引
+     */
+    private loadAndCacheImg;
+    /**
+     * 绘制九宫格抽奖
+     */
+    protected draw(): void;
+    /**
+     * 处理背景色
+     * @param x
+     * @param y
+     * @param width
+     * @param height
+     * @param background
+     * @param isActive
+     */
+    private handleBackground;
+    /**
+     * 刻舟求剑
+     */
+    private carveOnGunwaleOfAMovingBoat;
+    /**
+     * 对外暴露: 开始抽奖方法
+     */
+    play(): void;
+    /**
+     * 对外暴露: 缓慢停止方法
+     * @param index 中奖索引
+     */
+    stop(index?: number): void;
+    /**
+     * 实际开始执行方法
+     * @param num 记录帧动画执行多少次
+     */
+    private run;
+    /**
+     * 计算奖品格子的几何属性
+     * @param { array } [...矩阵坐标, col, row]
+     * @return { array } [...真实坐标, width, height]
+     */
+    private getGeometricProperty;
+    /**
+     * 换算渲染坐标
+     * @param x
+     * @param y
+     */
+    protected conversionAxis(x: number, y: number): [number, number];
+}
+
+declare type PrizeFontType = FontItemType & FontExtendType;
+declare type BlockImgType = ImgItemType & {};
+declare type PrizeImgType = ImgItemType;
+declare type BlockType = {
+    borderRadius?: BorderRadiusType;
+    background?: BackgroundType;
+    padding?: string;
+    paddingTop?: string | number;
+    paddingRight?: string | number;
+    paddingBottom?: string | number;
+    paddingLeft?: string | number;
+    imgs?: Array<BlockImgType>;
+};
+declare type PrizeType = {
+    borderRadius?: BorderRadiusType;
+    background?: BackgroundType;
+    fonts?: Array<PrizeFontType>;
+    imgs?: Array<PrizeImgType>;
+};
+declare type SlotType = {
+    order?: number[];
+    speed?: number;
+    direction?: 1 | -1;
+};
+declare type DefaultConfigType = {
+    /**
+     * vertical 为纵向旋转
+     * horizontal 为横向旋转
+     */
+    mode?: 'vertical' | 'horizontal';
+    /**
+     * 当排列方向 = `vertical`时
+     *    1 bottom to top
+     *   -1 top to bottom
+     * 当排列方向 = `horizontal`时
+     *    1 right to left
+     *   -1 left to right
+     */
+    direction?: 1 | -1;
+    rowSpacing?: number;
+    colSpacing?: number;
+    speed?: number;
+    accelerationTime?: number;
+    decelerationTime?: number;
+};
+declare type DefaultStyleType = {
+    borderRadius?: BorderRadiusType;
+    background?: BackgroundType;
+    fontColor?: PrizeFontType['fontColor'];
+    fontSize?: PrizeFontType['fontSize'];
+    fontStyle?: PrizeFontType['fontStyle'];
+    fontWeight?: PrizeFontType['fontWeight'];
+    lineHeight?: PrizeFontType['lineHeight'];
+    wordWrap?: PrizeFontType['wordWrap'];
+    lengthLimit?: PrizeFontType['lengthLimit'];
+    lineClamp?: PrizeFontType['lineClamp'];
+};
+declare type EndCallbackType = (prize: PrizeType | undefined) => void;
+interface SlotMachineConfig {
+    width: string | number;
+    height: string | number;
+    blocks?: Array<BlockType>;
+    prizes?: Array<PrizeType>;
+    slots?: Array<SlotType>;
+    defaultConfig?: DefaultConfigType;
+    defaultStyle?: DefaultStyleType;
+    end?: EndCallbackType;
+}
+
+declare class SlotMachine extends Lucky {
+    private blocks;
+    private prizes;
+    private slots;
+    private defaultConfig;
+    private _defaultConfig;
+    private defaultStyle;
+    private _defaultStyle;
+    private endCallback;
+    private _offscreenCanvas?;
+    private cellWidth;
+    private cellHeight;
+    private cellAndSpacing;
+    private widthAndSpacing;
+    private heightAndSpacing;
+    private FPS;
+    private scroll;
+    private stopScroll;
+    private endScroll;
+    private startTime;
+    private endTime;
+    /**
+     * 游戏当前的阶段
+     * step = 0 时, 游戏尚未开始
+     * step = 1 时, 此时处于加速阶段
+     * step = 2 时, 此时处于匀速阶段
+     * step = 3 时, 此时处于减速阶段
+     */
+    private step;
+    /**
+     * 中奖索引
+     * prizeFlag = undefined 时, 处于开始抽奖阶段, 正常旋转
+     * prizeFlag >= 0 时, 说明stop方法被调用, 并且传入了中奖索引
+     * prizeFlag === -1 时, 说明stop方法被调用, 并且传入了负值, 本次抽奖无效
+     */
+    private prizeFlag;
+    private prizeArea?;
+    private ImageCache;
+    /**
+     * 老虎机构造器
+     * @param config 配置项
+     * @param data 抽奖数据
+     */
+    constructor(config: UserConfigType, data: SlotMachineConfig);
+    protected resize(): void;
+    protected initLucky(): void;
+    /**
+     * 初始化数据
+     * @param data
+     */
+    private initData;
+    /**
+     * 初始化属性计算
+     */
+    private initComputed;
+    /**
+     * 初始化观察者
+     */
+    private initWatch;
+    /**
+     * 初始化 canvas 抽奖
+     */
+    init(): Promise<void>;
+    private initImageCache;
+    /**
+     * 根据索引单独加载指定图片并缓存
+     * @param cellName 模块名称
+     * @param cellIndex 模块索引
+     * @param imgName 模块对应的图片缓存
+     * @param imgIndex 图片索引
+     */
+    private loadAndCacheImg;
+    /**
+     * 绘制离屏canvas
+     */
+    protected drawOffscreenCanvas(): void;
+    /**
+     * 绘制背景区域
+     */
+    protected drawBlocks(): SlotMachine['prizeArea'];
+    /**
+     * 绘制老虎机抽奖
+     */
+    protected draw(): void;
+    /**
+     * 刻舟求剑
+     */
+    private carveOnGunwaleOfAMovingBoat;
+    /**
+     * 对外暴露: 开始抽奖方法
+     */
+    play(): void;
+    stop(index: number | number[]): void;
+    /**
+     * 让游戏动起来
+     * @param num 记录帧动画执行多少次
+     */
+    private run;
+    private displacement;
+    private displacementWidthOrHeight;
+}
+
+/**
+ * 切割圆角
+ * @param img 将要裁剪的图片对象
+ * @param radius 裁剪的圆角半径
+ * @returns 返回一个离屏 canvas 用于渲染
+ */
+declare const cutRound: (img: ImgType, radius: number) => ImgType;
+/**
+ * 透明度
+ * @param img 将要处理的图片对象
+ * @param opacity 透明度
+ * @returns 返回一个离屏 canvas 用于渲染
+ */
+declare const opacity: (img: ImgType, opacity: number) => ImgType;
+
+export { LuckyGrid, LuckyWheel, SlotMachine, cutRound, opacity };

+ 1 - 0
packageA/affiche/index.vue

@@ -120,6 +120,7 @@ export default {
                     console.log("更新通告列表", res)
                     if (this.cutoff(res.msg)) return;
                     this.list = res.data;
+                    this.$refs.List.paging(current, res, true)
                 })
             }
         },

+ 1 - 0
packageA/exam/index.vue

@@ -141,6 +141,7 @@ export default {
                     console.log("更新试卷列表", res)
                     if (this.cutoff(res.msg)) return;
                     this.list = res.data;
+                    this.$refs.List.paging(current, res, true)
                 })
             }
         },

+ 2 - 1
packageA/exam/result.vue

@@ -130,6 +130,7 @@ export default {
                     console.log("更新试卷列表", res)
                     if (this.cutoff(res.msg)) return;
                     this.list = res.data;
+                    this.$refs.List.paging(current, res, true)
                 })
             }
         },
@@ -175,7 +176,7 @@ export default {
             })
             if (e.一级分类 == '') {
                 crumbs.push({
-                    classname:'全部',
+                    classname: '全部',
                     parentid: ''
                 })
             }

+ 1 - 0
packageA/resourceLibrary/index.vue

@@ -132,6 +132,7 @@ export default {
                     console.log("更新装备资源库列表", res)
                     if (this.cutoff(res.msg)) return;
                     this.list = res.data;
+                    this.$refs.List.paging(current, res, true)
                 })
             }
         },

+ 4 - 0
pages.json

@@ -80,6 +80,10 @@
 			"path": "insert/member"
 		}, {
 			"path": "center/detail"
+		}, {
+			"path": "lottery/shareable"
+		}, {
+			"path": "lottery/unshareable"
 		}]
 	}, {
 		"root": "cloud",

+ 93 - 55
pages/index/index.vue

@@ -34,81 +34,54 @@ export default {
 		return {
 			swiperItemID: 'index',
 			page: '首页',
-			user: {
-				wechatBindUserid: 0,
-				userName: ""
-			},
-			sa_storeid: 0
+			sa_storeid: 0,
+			funs: [],
 		}
 	},
 	onLoad(options) {
 		if (options.wechatBindUserid) {
-			this.user.wechatBindUserid = options.wechatBindUserid;
-			this.user.userName = options.userName;
+			this.funs.push({
+				fun: this.wechatBind.bind(this),
+				value: {
+					wechatBindUserid: options.wechatBindUserid,
+					userName: options.userName,
+				}
+			})
 		} else if (options.sa_storeid) {
 			this.sa_storeid = options.sa_storeid;
 		}
 		if (options.q) {
 			let data = this.getUrlParams(options.q);
-			if (data.wechatBindUserid) this.user = data;//绑定账号
-			if (data.sa_storeid) this.sa_storeid = data.sa_storeid;//锁定门店
+			switch (data.funName) {
+				case 'wechatBind':
+					this.funs.push({
+						fun: this.wechatBind.bind(this),
+						value: data
+					})
+					break;
+				case 'getStore':
+					this.sa_storeid = data.sa_storeid;
+					break;
+				case 'BindSalesman':
+					this.funs.push({
+						fun: this.bindSalesman.bind(this),
+						value: data
+					})
+					break;
+			}
 		}
+
 	},
 	onShow() {
 		this.isInitializeLogin(render.bind(this))
 		function render() {
-			let that = this;
+			if (this.funs.length) this.funs.forEach(v => v.fun(v.value));
 			this.$Http.changePage = function (itemId, page, params) {
 				this.$refs.pages.onClick(itemId, page, false, params)
 			}.bind(this)
 			// #ifdef MP-WEIXIN
 			this.updatePageData(this.swiperItemID, this.page)
 			// #endif
-			if (this.user.wechatBindUserid) {
-				console.log("被邀请绑定账号", this.user);
-				uni.showModal({
-					title: '提醒',
-					content: `账号"${this.user.userName}"是否与当前微信号绑定`,
-					confirmText: '确定绑定',
-					success: function ({ confirm }) {
-						if (confirm) uni.login({
-							success(res) {
-								that.$Http.basic({
-									"id": 20240516090402,
-									"content": {
-										"wechat_code": res.code,
-										"isbinging": 1,
-										"wechatuserinfo": "",
-										"sys_enterprise_hrid": that.user.wechatBindUserid
-									}
-								}).then(s => {
-									console.log("绑定账号", s)
-									uni.showModal({
-										title: '提示',
-										content: s.msg == '成功' ? '绑定成功' : s.msg,
-										showCancel: false,
-										success: function ({ confirm }) {
-											if (confirm) {
-												if (s.msg == '成功') that.$Login.wechatLogin().then(() => {
-													uni.reLaunch({
-														url: '/pages/index/index'
-													})
-													that.user = {
-														wechatBindUserid: 0,
-														userName: ""
-													}
-												})
-											}
-										}
-									});
-								})
-							}
-						})
-					}
-				});
-			} else {
-				console.log("this.user", this.user)
-			}
 		}
 	},
 	methods: {
@@ -131,6 +104,71 @@ export default {
 				detail.callBack()
 			}
 			console.log("切换页面", detail)
+		},
+		wechatBind(user) {
+			console.log("被邀请绑定账号", user);
+			let that = this;
+			uni.showModal({
+				title: '提醒',
+				content: `账号"${user.userName}"是否与当前微信号绑定`,
+				confirmText: '确定绑定',
+				success: function ({ confirm }) {
+					if (confirm) uni.login({
+						success(res) {
+							that.$Http.basic({
+								"id": 20240516090402,
+								"content": {
+									"wechat_code": res.code,
+									"isbinging": 1,
+									"wechatuserinfo": "",
+									"sys_enterprise_hrid": user.wechatBindUserid
+								}
+							}).then(s => {
+								console.log("绑定账号", s)
+								uni.showModal({
+									title: '提示',
+									content: s.msg == '成功' ? '绑定成功' : s.msg,
+									showCancel: false,
+									success: function () {
+										that.$Login.wechatLogin().then(() => uni.reLaunch({
+											url: '/pages/index/index'
+										}))
+									}
+								});
+							})
+						}
+					})
+				}
+			});
+		},
+		bindSalesman(user) {
+			console.log("被邀请绑定业务员", user);
+			let that = this;
+			uni.showModal({
+				title: '提醒',
+				content: `业务员账号"${user.userName}"是否与当前微信号绑定`,
+				confirmText: '确定绑定',
+				success: function ({ confirm }) {
+					if (confirm) that.$Http.basic({
+						"id": 20240524090002,
+						"content": {
+							"hrid": user.hrid
+						}
+					}).then(s => {
+						console.log("绑定账号", s)
+						uni.showModal({
+							title: '提示',
+							content: s.msg == '成功' ? '绑定成功' : s.msg,
+							showCancel: false,
+							success: function () {
+								that.$Login.wechatLogin().then(() => uni.reLaunch({
+									url: '/pages/index/index'
+								}))
+							}
+						});
+					})
+				}
+			});
 		}
 	}
 }

+ 1 - 0
pages/index/index/casePages/design.vue

@@ -103,6 +103,7 @@ export default {
                         return v
                     })
                     this.list = res.data;
+                    this.$refs.List.paging(current, res, true)
                     if (data) handle();
 
                 })

+ 1 - 0
store/center/detail.vue

@@ -310,6 +310,7 @@ export default {
                         if (this.cutoff(res.msg)) return;
                         this.$refs.List.setHeight()
                         this.list = res.data;
+                        this.$refs.List.paging(current, res, true)
                     })
                 }
             }.bind(this)

+ 1 - 0
store/deliveryAddress/index.vue

@@ -93,6 +93,7 @@ export default {
                 console.log("更新收货地址列表", res)
                 if (this.cutoff(res.msg)) return;
                 this.list = res.data;
+                this.$refs.List.paging(this.content, res, true)
             })
         },
         toAdd() {

+ 1 - 0
store/insert/member.vue

@@ -73,6 +73,7 @@ export default {
                     console.log("更新人员列表", res)
                     if (this.cutoff(res.msg)) return;
                     this.list = res.data;
+                    this.$refs.List.paging(current, res, true)
                 })
             }
         },

+ 395 - 0
store/lottery/modules/sudoku.vue

@@ -0,0 +1,395 @@
+<template>
+    <view class="box">
+        <view class="lottery-box">
+            <navigator class="my-list" url="/cloud/winningNews/index">
+                我的奖品
+            </navigator>
+            <image class="bg-image"
+                src="https://yossys06593.obs.cn-east-3.myhuaweicloud.com:443/202405281716860202553Be55ba55.webp" />
+            <view class="lottery" v-if="prizes.length && showPrizes">
+                <view>
+                    <LuckyGrid ref="myLucky" width="590rpx" height="590rpx" :prizes="prizes" :buttons="buttons"
+                        :defaultStyle="defaultStyle" @start="startCallBack" @end="endCallBack" />
+                </view>
+            </view>
+            <view class="usable-count">
+                您还有<text class="count">{{ usableCount }}</text>抽奖机会
+            </view>
+        </view>
+        <view class="winners-list" v-if="winningList.length">
+            <image class="image"
+                src="https://yossys06593.obs.cn-east-3.myhuaweicloud.com:443/202405281716863577428B1faf5081.webp"
+                mode="widthFix" />
+            <view class="content">
+                <view class="title">
+                    <view class="text">
+                        抽奖名单
+                    </view>
+                </view>
+                <swiper class="swiper" autoplay easing-function="linear" interval="1000" duration="1000" circular vertical
+                    :display-multiple-items="7">
+                    <swiper-item v-for="item in winningList" :key="item.sa_awardmxid">
+                        <view v-if="item.createuserid" class="swiper-item u-line-2">
+                            {{ item.name ? item.name : '用户' + item.createuserid }} <text
+                                style="padding: 0 5px;">抽中了</text>{{ item.awardname }}
+                        </view>
+                        <view v-else></view>
+                    </swiper-item>
+                </swiper>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+import LuckyGrid from '@/components/@lucky-canvas/uni/lucky-grid'
+export default {
+    components: { LuckyGrid },
+    props: {
+        sa_awardid: {
+            type: [Number || String]
+        },
+        shareuserid: {
+            type: [Number || String]
+        }
+    },
+    data() {
+        return {
+            prizes: [],
+            buttons: [{
+                background: 'rgba(0,0,0,0)',
+                x: 1, y: 1,
+                imgs: [{
+                    src: 'https://yossys06593.obs.cn-east-3.myhuaweicloud.com:443/202405281716861339513B3a575413.webp',
+                    width: '183.34rpx',
+                    height: '183.34rpx',
+                }],
+            }],
+            defaultStyle: {
+                background: '#FFFFFF',
+                width: '183.34rpx',
+                height: '183.34rpx',
+            },
+            usableCount: 0,
+            loading: false,
+            winningList: [],
+            tips: '',
+            showPrizes: true,
+        }
+    },
+    methods: {
+        init() {
+            console.log("this.sa_awardid", this.sa_awardid)
+            try {
+                this.$Http.basic({
+                    "id": 20240514131402,
+                    content: {
+                        "sa_awardid": this.sa_awardid,
+                        "where": {
+                            "condition": "",
+                            "type": ""
+                        }
+                    }
+                }).then(res => {
+                    console.log("奖品列表", res)
+                    if (this.cutoff(res.msg)) return;
+                    let prizes = [
+                        { index: 0, x: 0, y: 0 },
+                        { index: 2, x: 2, y: 0 },
+                        { index: 6, x: 0, y: 2 },
+                        { index: 4, x: 2, y: 2 },
+                        { index: 1, x: 1, y: 0 },
+                        { index: 3, x: 2, y: 1 },
+                        { index: 5, x: 1, y: 2 },
+                        { index: 7, x: 0, y: 1 },
+                    ].map(v => {
+                        v.borderRadius = '20rpx';
+                        v.imgs = [{
+                            src: 'https://yossys06593.obs.cn-east-3.myhuaweicloud.com:443/202405291716965428111B4602d616.webp',
+                            width: '50%',
+                            top: '20%'
+                        }]
+                        return v
+                    })
+                    res.data.forEach((v, i) => {
+                        v.imgs = v.attinfos.map(img => {
+                            return {
+                                src: img.url,
+                                width: '50%',
+                                top: '25%'
+                            }
+                        })
+                        prizes[i] = Object.assign(prizes[i], v);
+                    });
+                    this.prizes = prizes.sort((a, b) => {
+                        return a.index - b.index
+                    });
+                })
+            } catch (error) { }
+            this.queryAwardCount();
+            this.getWinningList();
+        },
+        startCallBack() {
+            let that = this;
+            if (this.tips) return uni.showToast({
+                title: this.tips,
+                icon: 'none',
+                duration: 1500,
+            });
+            if (this.loading || this.usableCount == 0) return;
+            this.loading = true;
+            this.$refs.myLucky.play()
+            that.$Http.basic({
+                "content": {
+                    "sa_awardid": that.sa_awardid,
+                    "shareuserid": that.shareuserid,
+                },
+                "id": 20240514134002,
+            }).then(res => {
+                console.log('抽奖结果', res)
+                if (this.cutoff(res.msg)) {
+                    this.showPrizes = false;
+                    setTimeout(() => {
+                        this.showPrizes = true;
+                    })
+                    that.queryAwardCount();
+                    that.getWinningList();
+                    return
+                };
+                const index = that.prizes.findIndex(v => v.sa_awarditemsid == res.data.sa_awarditemsid);
+                that.$refs.myLucky.stop(index)
+                that.queryAwardCount();
+                that.getWinningList();
+                setTimeout(() => {
+                    that.loading = false;
+                    that.showWinningResult(res.data, index);
+                }, 5000);
+            })
+        },
+        showWinningResult(data, index) {
+            console.log("中奖结果", data)
+            let that = this;
+            uni.showModal({
+                title: '恭喜您抽中',
+                content: data.awardname,
+                showCancel: false,
+                confirmText: '选择地址',
+                success: function ({ confirm }) {
+                    if (confirm) {
+                        uni.navigateTo({
+                            url: '/store/deliveryAddress/index'
+                        })
+                        that.$Http.selectAddress = (item) => {
+                            uni.showModal({
+                                title: '提示',
+                                content: `是否确定选择“${item.address}”作为收货地址?`,
+                                success: (success) => {
+                                    if (success.confirm) that.$Http.basic({
+                                        id: "2024052910464202",
+                                        content: {
+                                            sa_awardmxid: item.sa_awardmxid,
+                                            name: item.name,
+                                            phonenumber: item.phonenumber,
+                                            province: item.province,
+                                            city: item.city,
+                                            county: item.county,
+                                            address: item.address,
+                                        }
+                                    }).then(s => {
+                                        if (that.cutoff(s.msg, '设置成功', true, '1000')) return;
+                                    })
+                                },
+                            })
+                        }
+                    }
+                },
+                fail: (err) => {
+                    console.log(err)
+                }
+            });
+        },
+        getWinningList() {
+            this.$Http.basic({
+                "content": {
+                    "sa_awardid": this.sa_awardid,
+                    "pageNumber": 1,
+                    "pageSize": 20
+                },
+                "id": 20240514133902
+            }).then(res => {
+                console.log("中奖人员", res)
+                if (this.cutoff(res.msg)) return;
+                if (res.data.length < 7) {
+                    let len = res.data.length;
+                    for (let index = 0; index < (7 - len); index++) {
+                        res.data.push({})
+                    }
+                }
+                this.winningList = res.data;
+            })
+        },
+        queryAwardCount() {
+            if (uni.getStorageSync('userMsg').usertype == 99) {
+                this.$Http.basic({
+                    "classname": "sysmanage.develop.datafunction.datafunction",
+                    "method": "execute",
+                    "content": {
+                        "functionname": "queryAwardCount",
+                        "parameter": {
+                            "sa_awardid": this.sa_awardid
+                        }
+                    }
+                }).then(res => {
+                    console.log("抽奖可用次数", res)
+                    if (this.cutoff(res.msg)) return;
+                    this.usableCount = res.data.length ? res.data[0].count : 0;
+                })
+            } else {
+                this.tips = '内部人员不可参与抽奖';
+            }
+        },
+        endCallBack(prize) {
+            console.log("抽到的奖品", prize)
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.box {
+    width: 100vw;
+    min-height: 100vh;
+    background: linear-gradient(90deg, #FE5A46 0%, #F11F46 100%);
+
+    .lottery-box {
+        position: relative;
+        width: 100vw;
+        height: 511px;
+
+        .my-list {
+            position: absolute;
+            top: 20px;
+            left: 0;
+            width: 86px;
+            height: 40px;
+            line-height: 40px;
+            text-align: center;
+            background: linear-gradient(180deg, #FAD96D 0%, #FFC300 4%, #FFCD2B 16%, #FFDF77 42%, #FFD241 70%, #FFC300 94%, #FC9228 100%);
+            border-radius: 0px 20px 20px 0px;
+            font-family: Source Han Sans SC, Source Han Sans SC;
+            font-weight: bold;
+            font-size: 14px;
+            color: #C30D23;
+            z-index: 2;
+        }
+
+        .bg-image {
+            position: absolute;
+            width: 100vw;
+            height: 511px;
+            top: 0;
+            left: 0;
+            z-index: 1;
+            vertical-align: bottom;
+        }
+
+        .lottery {
+            position: absolute;
+            width: 100%;
+            z-index: 2;
+            top: 140px;
+        }
+
+        .usable-count {
+            position: absolute;
+            bottom: 15px;
+            width: 100vw;
+            text-align: center;
+            font-family: Source Han Sans SC, Source Han Sans SC;
+            font-weight: bold;
+            font-size: 14px;
+            color: #FFFFFF;
+
+            .count {
+                height: 29px;
+                font-family: Source Han Sans SC, Source Han Sans SC;
+                font-weight: 800;
+                font-size: 20px;
+                color: #FAD96D;
+                padding: 0 10px;
+            }
+        }
+    }
+
+
+
+    .winners-list {
+        width: 100vw;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        padding-bottom: 20px;
+
+        .image {
+            width: 355px;
+        }
+
+        .title {
+            position: relative;
+            width: 80px;
+            height: 29px;
+            margin: 0 auto;
+
+            .text {
+                position: absolute;
+                top: 0px;
+                left: 0;
+                width: 80px;
+                line-height: 29px;
+                text-align: center;
+                font-family: Source Han Sans SC, Source Han Sans SC;
+                font-weight: bold;
+                font-size: 20px;
+                color: #333333;
+                z-index: 2;
+            }
+        }
+
+        .title::after {
+            content: '';
+            position: absolute;
+            bottom: 0px;
+            left: 0;
+            width: 80px;
+            height: 8px;
+            background: #FAD96D;
+            border-radius: 5px;
+            z-index: 1;
+        }
+
+        .content {
+            background: #fff;
+            padding: 0 15px 20px;
+            width: 669.7672675rpx;
+            box-sizing: border-box;
+
+            .swiper {
+                width: 100%;
+                height: 300px;
+                margin-top: 20px;
+
+                .swiper-item {
+                    width: 100%;
+                    height: 40px;
+                    text-align: center;
+                    line-height: 20px;
+                    font-family: Source Han Sans SC, Source Han Sans SC;
+                    font-size: 14px;
+                    color: #666666;
+                    overflow: hidden;
+                }
+            }
+        }
+    }
+}
+</style>

+ 56 - 0
store/lottery/shareable.vue

@@ -0,0 +1,56 @@
+<template>
+    <view>
+        <sudoku ref="sudoku" :sa_awardid="sa_awardid" :shareuserid="shareuserid" />
+    </view>
+</template>
+
+<script>
+import sudoku from "./modules/sudoku"
+export default {
+    components: { sudoku },
+    data() {
+        return {
+            sa_awardid: 0,
+            shareuserid: 0,
+            detail: {},
+        }
+    },
+    onLoad(options) {
+        this.sa_awardid = options.id || 0;
+        this.shareuserid = options.userid || 0;
+        uni.setNavigationBarTitle({
+            title: '活动抽奖'
+        });
+    },
+    onShow() {
+        this.$Http.basic({
+            "id": 20240514101502,
+            "content": {
+                "sa_awardid": this.sa_awardid,
+            }
+        }).then(res => {
+            console.log("抽奖详情", res)
+            if (this.cutoff(res.msg)) return;
+            this.detail = res.data;
+            this.$refs.sudoku.init();
+        })
+    }, methods: {
+        getSheraDate() {
+            let detail = this.detail;;
+            return {
+                title: detail.name, // 标题
+                path: "/store/lottery/shareable?sa_awardid=" + detail.sa_awardid + '&shareuserid=' + uni.getStorageSync('userMsg').userid, // 分享路径
+                imageUrl: ""// 分享图
+            };
+        }
+    },
+    onShareAppMessage() {
+        return this.getSheraDate()
+    },
+    onShareTimeline() {
+        return this.getSheraDate()
+    }
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 41 - 0
store/lottery/unshareable.vue

@@ -0,0 +1,41 @@
+<template>
+    <view>
+        <sudoku ref="sudoku" :sa_awardid="sa_awardid" :shareuserid="shareuserid" />
+    </view>
+</template>
+
+<script>
+import sudoku from "./modules/sudoku"
+export default {
+    components: { sudoku },
+    data() {
+        return {
+            sa_awardid: 0,
+            shareuserid: 0,
+            detail: {},
+        }
+    },
+    onLoad(options) {
+        this.sa_awardid = options.id || 0;
+        this.shareuserid = options.userid || 0;
+        uni.setNavigationBarTitle({
+            title: '活动抽奖'
+        });
+    },
+    onShow() {
+        this.$Http.basic({
+            "id": 20240514101502,
+            "content": {
+                "sa_awardid": this.sa_awardid,
+            }
+        }).then(res => {
+            console.log("抽奖详情", res)
+            if (this.cutoff(res.msg)) return;
+            this.detail = res.data;
+            this.$refs.sudoku.init();
+        })
+    },
+}
+</script>
+
+<style lang="scss" scoped></style>

+ 1 - 0
team/agency/check.vue

@@ -74,6 +74,7 @@ export default {
                         if (this.cutoff(res.msg)) return;
                         this.$refs.List.setHeight()
                         this.list = this.$refs.storeList.handleList(res.data);
+                        this.$refs.List.paging(current, res, true)
                     })
                 }
             }.bind(this)

+ 1 - 0
team/team/modules/agency.vue

@@ -114,6 +114,7 @@ export default {
                         if (this.cutoff(res.msg)) return;
                         this.$refs.List.setHeight()
                         this.list = res.data;
+                        this.$refs.List.paging(current, res, true)
                     })
                 }
             }.bind(this)

+ 1 - 0
team/team/modules/store.vue

@@ -131,6 +131,7 @@ export default {
                         if (this.cutoff(res.msg)) return;
                         this.$refs.List.setHeight()
                         this.list = this.$refs.storeList.handleList(res.data);
+                        this.$refs.List.paging(current, res, true)
                     })
                 }
             }.bind(this)

+ 1 - 0
team/team/modules/users.vue

@@ -85,6 +85,7 @@ export default {
                         if (this.cutoff(res.msg)) return;
                         this.$refs.List.setHeight()
                         this.list = res.data;
+                        this.$refs.List.paging(current, res, true)
                     })
                 }
             }.bind(this)

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels