index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. <template>
  2. <transition name="msgbox-fade">
  3. <div class="pub-wrapper" v-if="visible">
  4. <div class="pub-mask" @click="visible = false"></div>
  5. <div class="packet-send-wrap">
  6. <back-bar :title="$t('redPacket.title')" class="redpacket-backbar" v-if="meechatType=='h5'" @onBack="hidePopup"></back-bar>
  7. <div class="send-wrap" :class="[{'is-private':isPrivate}]">
  8. <i class="el-icon-close" @click="hidePopup"></i>
  9. <i class="el-icon-question" @click="helpShow = true"></i>
  10. <h3 class="title">{{ $t('redPacket.title') }}</h3>
  11. <p class="redpacket-tips" :class="{'hidden': !tips}">{{tips}}</p>
  12. <div class="main-box">
  13. <div class="input-item">
  14. <span class="text">
  15. <!--<em v-if="!isPrivate">{{ $t('redPacket.random') }}</em>-->
  16. {{ $t('redPacket.totalAmount') }}
  17. </span>
  18. <div class="packet-box" >
  19. <input type="number" v-model.number="money" @blur="inputBlur" placeholder="0.00">
  20. <div class="unit">
  21. <div class="cur-unit has-arrow">{{symbol}}</div>
  22. <div class="code-menu">
  23. <div :class="['code-item',{'disabled':loginType!='eos'}]" @click="changeSymbol('EOS')">EOS</div>
  24. <div :class="['code-item',{'disabled':loginType!='meetone'}]" @click="changeSymbol('MEETONE')" v-if="loginType=='meetone'">MEETONE</div>
  25. <!-- <div :class="['code-item',{'disabled':loginType!='eth'}]" @click="changeSymbol('ETH')">ETH</div> -->
  26. <div class="code-item" @click="changeSymbol(group.eosInfo.token)" v-if="group.eosInfo">{{group.eosInfo.token}}</div>
  27. </div>
  28. </div>
  29. </div>
  30. </div>
  31. <p class="input-tips" v-if="!isPrivate">
  32. {{ $t('redPacket.tip1') }}
  33. </p>
  34. <div class="input-item pack-num-input" v-if="!isPrivate">
  35. <span class="text">{{ $t('redPacket.num') }}</span>
  36. <div class="packet-box">
  37. <input type="number" v-model.number="packetNum" :placeholder="$t('redPacket.placeholder1')" @blur="inputBlur">
  38. <div class="unit">{{ $t('redPacket.unit') }}</div>
  39. </div>
  40. </div>
  41. <p class="group-user-num" v-if="!isPrivate">
  42. {{ $t('redPacket.tip2', {num: group.membersNum}) }}
  43. </p>
  44. <textarea class="words" v-model="word" :placeholder="$t('redPacket.memo')"></textarea>
  45. <div class="sum">
  46. {{amountSum}} <span>{{symbol}}</span>
  47. </div>
  48. <button class="send-btn" @click="sendPacket" :class="{'is-disable': !amountSum || !packetNum, 'loading': isLoading}">
  49. <i v-if="isLoading" class="el-icon-loading"></i> {{ $t('redPacket.sendBtn') }}
  50. </button>
  51. </div>
  52. <p class="bot">{{ $t('redPacket.tip3') }}</p>
  53. </div>
  54. <div class="help-wrap" v-show="helpShow">
  55. <i class="el-icon-close" @click="helpShow = false"></i>
  56. <h3 class="title">{{ $t('redPacket.helpTitle') }}</h3>
  57. <div class="content">
  58. <div class="item">
  59. {{ $t('redPacket.helpRule1') }}
  60. </div>
  61. <div class="item">
  62. {{ $t('redPacket.helpRule2') }}
  63. </div>
  64. <div class="item">
  65. {{ $t('redPacket.helpRule3') }}
  66. </div>
  67. </div>
  68. </div>
  69. </div>
  70. </div>
  71. </transition>
  72. </template>
  73. <script>
  74. import { mapState, mapGetters } from 'vuex'
  75. import { Message } from 'element-ui'
  76. import NP from 'number-precision'
  77. import EosHelper from '@/util/eosHelper.js'
  78. import EthHelper from '@/util/ethHelper.js'
  79. import { getMeechatType, getUserOpt, mobileInputBlur, showError } from '@/util/util'
  80. import backBar from '@/components/backBar'
  81. export default {
  82. name: 'packetSend',
  83. data () {
  84. let loginType = getUserOpt('loginType') || 'eos'
  85. return {
  86. visible: true,
  87. helpShow: false,
  88. money: 1,
  89. packetNum: 1,
  90. word: this.$t('redPacket.memo'),
  91. tips: '',
  92. loginType: loginType,
  93. symbol: 'EOS', // 单位
  94. isLoading: false,
  95. isGameToken: false, // 是否为游戏代币
  96. meechatType: getMeechatType()// meechat版本
  97. }
  98. },
  99. components: {
  100. backBar
  101. },
  102. computed: {
  103. ...mapState([
  104. 'account',
  105. 'group',
  106. 'curSession',
  107. 'scatter',
  108. 'userInfo'
  109. ]),
  110. ...mapGetters(['isPrivate']),
  111. amountSum () {
  112. return this.money
  113. },
  114. minSum () {
  115. return this.isGameToken ? NP.divide(this.group.eosInfo.min_amount, 10000) : 0.1
  116. },
  117. maxSum () {
  118. return this.isGameToken ? NP.divide(this.group.eosInfo.max_amount, 10000) : 200
  119. }
  120. },
  121. watch: {
  122. money (val) {
  123. if (val > this.maxSum) {
  124. this.money = this.maxSum
  125. this.showTip(`${this.$t('redPacket.maxMoneyTip')} ${this.maxSum} ${this.symbol}`)
  126. }
  127. if (val && val / this.packetNum < 0.01) {
  128. this.money = NP.times(this.packetNum, 0.01)
  129. // this.showTip(`${this.$t('redPacket.maxMoneyTip')} 0.01 ${this.symbol}`)
  130. this.showTip(`${this.$t('redPacket.singleMinMoneyTip')} 0.01 ${this.symbol}`)
  131. }
  132. },
  133. packetNum (to, from) {
  134. if (this.money && NP.divide(this.money, to) < 0.01) {
  135. this.packetNum = from
  136. this.showTip(`${this.$t('redPacket.singleMinMoneyTip')} 0.01 ${this.symbol}`)
  137. }
  138. if (to > 100) {
  139. this.packetNum = 100
  140. this.showTip(`${this.$t('redPacket.maxNumberTip')} 100 个`)
  141. }
  142. }
  143. },
  144. methods: {
  145. inputBlur () {
  146. mobileInputBlur()
  147. },
  148. changeSymbol (type) {
  149. this.symbol = type
  150. // 游戏代币判断
  151. this.isGameToken = this.group.eosInfo && this.group.eosInfo.token == type
  152. },
  153. hidePopup () {
  154. this.visible = false
  155. },
  156. showTip (msg, timeout = 3000) {
  157. this.tips = msg
  158. setTimeout(() => {
  159. this.tips = ''
  160. }, timeout)
  161. },
  162. // 检测是否有发红包权限
  163. checkCanSend () {
  164. let loginType = this.loginType
  165. let checksSymbol = this.symbol.toLowerCase()
  166. if (checksSymbol == 'eth') {
  167. if (!window.ethereum || !window.web3) {
  168. showError('你还没有安装eth插件')
  169. return false
  170. }
  171. } else {
  172. // eos币种校验
  173. let eosType = getUserOpt('eosType') || 'eos'
  174. // 判断登录
  175. if (loginType != 'eos' && loginType != 'meetone') {
  176. Message({
  177. message: this.$t('redPacket.sendForEosTips'),
  178. type: 'error'
  179. })
  180. return false
  181. }
  182. // 判断绑定
  183. if (checksSymbol == 'eos' || checksSymbol == 'meetone') {
  184. let flag = this.userInfo.binds.some((item) => {
  185. return item.type == checksSymbol && item.account
  186. })
  187. if (!flag) {
  188. Message({
  189. message: this.$t('redPacket.bindForEosTips', { 'type': checksSymbol }),
  190. type: 'error'
  191. })
  192. return false
  193. }
  194. }
  195. // 判断scatter现在身份和登录身份是否一致
  196. if (loginType != eosType) {
  197. Message({
  198. message: '重新检查下scatter身份',
  199. type: 'error'
  200. })
  201. return false
  202. }
  203. }
  204. return true
  205. },
  206. async sendPacket () {
  207. if (!this.checkCanSend()) return
  208. if (this.money < this.minSum) {
  209. this.showTip(`${this.$t('redPacket.minMoneyTip')} ${this.minSum} ${this.symbol}`)
  210. return false
  211. }
  212. this.isLoading = true
  213. switch (this.symbol) {
  214. case 'Tron':
  215. this.transferTron()
  216. break
  217. case 'ETH':
  218. this.transferEth()
  219. break
  220. default:
  221. this.transferEos()
  222. break
  223. }
  224. },
  225. // eos转换
  226. async transferEos () {
  227. let eosAmount = this.amountSum.toFixed(4) + ` ${this.symbol}`
  228. let toAccount = this.symbol == 'MEETONE' ? 'meechat.m' : 'meechatadmin'
  229. let memo = {
  230. type: 'redpack',
  231. num: this.packetNum,
  232. memo: this.word,
  233. sid: this.isPrivate ? this.curSession : this.group.groupId
  234. }
  235. let tokenCode = this.isGameToken ? this.group.eosInfo.token_code : 'eosio.token'
  236. let symbol = this.symbol
  237. let [balance] = await EosHelper.getCurrencyBalance(tokenCode, this.account.name, symbol)
  238. if (balance) {
  239. let userBalance = this.isGameToken ? balance.replace(new RegExp('\\s' + symbol), '') : balance.replace(/\sEOS/, '')
  240. if (this.amountSum > Number(userBalance)) {
  241. Message({
  242. message: this.$t('public.noMoney'),
  243. type: 'error'
  244. })
  245. this.isLoading = false
  246. return
  247. }
  248. if (this.isGameToken) {
  249. // 代币
  250. let tokenCode = this.group.eosInfo.token_code
  251. EosHelper.doSymbolTransfer(this.account.name, toAccount, eosAmount, JSON.stringify(memo), this.account.authority, tokenCode)
  252. .then(res => {
  253. this.hidePopup()
  254. }).catch(msg => {
  255. if (!msg.type) {
  256. let json = JSON.parse(msg)
  257. let details = json.error.details
  258. Message({
  259. message: details[0].message,
  260. type: 'error'
  261. })
  262. }
  263. }).finally(() => {
  264. this.isLoading = false
  265. })
  266. } else {
  267. // eos/meetone
  268. EosHelper.transfer(this.account.name, toAccount, eosAmount, JSON.stringify(memo), this.account.authority)
  269. .then((res) => {
  270. this.hidePopup()
  271. }).catch(msg => {
  272. if (!msg.type) {
  273. let json = JSON.parse(msg)
  274. let details = json.error.details
  275. Message({
  276. message: details[0].message,
  277. type: 'error'
  278. })
  279. }
  280. }).finally(() => {
  281. this.isLoading = false
  282. })
  283. }
  284. } else {
  285. Message({
  286. message: this.$t('public.noMoney'),
  287. type: 'error'
  288. })
  289. this.isLoading = false
  290. }
  291. },
  292. async transferEth () {
  293. try {
  294. await EthHelper.doTransfer(this.money)
  295. this.hidePopup()
  296. } catch (e) {
  297. this.isLoading = false
  298. }
  299. },
  300. transferTron () {
  301. }
  302. },
  303. mounted () {
  304. }
  305. }
  306. </script>
  307. <style lang="scss">
  308. @import './style.scss';
  309. </style>