My SMM panel
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

167 行
4.9 KiB

  1. <template>
  2. <div>
  3. <div class="services-menu">
  4. <a href="#new-order" :class="{selected: page == 'new-order'}">Services</a>
  5. <a href="#credits" :class="{selected: page == 'credits'}">Credits</a>
  6. <div :class="page" class="menu-slider"><div></div></div>
  7. </div>
  8. <h4 class="credits-display"><img class="icon" src="../../images/coin-stack.svg" alt=""><span> {{credits.toLocaleString('en')}}</span></h4>
  9. <template v-if="page == 'new-order'">
  10. <div class="services-legend">
  11. <h5>Name</h5><h5>Credits per 1000</h5><h5>Min Qt.</h5><h5>Max Qt.</h5>
  12. </div>
  13. <ServicePane :site="'youtube'" :services="services"
  14. @select="select"></ServicePane> <ServicePane :site="'instagram'"
  15. :services="services" @select="select"></ServicePane> <ServicePane
  16. :site="'twitter'" :services="services" @select="select"></ServicePane>
  17. <ServicePane :site="'tiktok'" :services="services"
  18. @select="select"></ServicePane>
  19. <div id="overlay" v-if="selected">
  20. <div v-if="!completed" class="overlay-item">
  21. <img @click="completed = false; selected = null" class="cancel icon"
  22. src="../../images/cancel-icon2.svg" alt=""/>
  23. <img v-if="selected.site == 'youtube'" class="icon"
  24. src="../../images/youtube-icon.svg" alt=""/>
  25. <img v-if="selected.site == 'instagram'" class="icon"
  26. src="../../images/instagram-icon.svg" alt=""/>
  27. <img v-if="selected.site == 'twitter'" class="icon"
  28. src="../../images/twitter.svg" alt=""/>
  29. <img v-if="selected.site == 'tiktok'" class="icon"
  30. src="../../images/tik-tok.svg" alt=""/>
  31. <h3>{{selected.name}}</h3>
  32. <h4>Cost: {{cost.toLocaleString('en')}}</h4>
  33. <h4>Quantity</h4>
  34. <div><input required :min="selected.minimum" :max="selected.maximum"
  35. type="number" v-model="amount" id="selQty"><span> /
  36. {{selected.maximum.toLocaleString('en')}}</span></div>
  37. <template v-if="selected.modifier == 'location'">
  38. <h4>Location</h4>
  39. <div><select required id="country" name="">
  40. <option value="usa">USA</option>
  41. <option value="canada">Canada</option>
  42. <option value="uk">United Kingdom</option>
  43. <option value="germany">Germany</option>
  44. <option value="france">France</option>
  45. </select>
  46. </div>
  47. </template>
  48. <h4>URL</h4>
  49. <div><input required type="url" id="url" v-model="url"></div>
  50. <button @click="buyService" :disabled="paying">Submit<loading
  51. v-if="paying"></loading></button>
  52. <p id="overlay-error"></p>
  53. </div>
  54. <div class="overlay-item" v-else-if="completed">
  55. <img @click="completed = false; selected = null" class="cancel icon"
  56. src="../../images/cancel-icon2.svg" alt=""/>
  57. <img class="icon" src="../../images/checked2.svg" alt=""/>
  58. <h3>Success!</h3>
  59. </div>
  60. </div>
  61. </template>
  62. <credits :token="token" v-if="page == 'credits'"></credits>
  63. </div>
  64. </template>
  65. <script>
  66. import ServicePane from './service-pane.vue'
  67. import Credits from './credits.vue'
  68. import Loading from '../icons/loading.vue'
  69. function select(service) {
  70. this.completed = false
  71. this.selected = service
  72. }
  73. function cost() {
  74. return Math.ceil(this.selected.price * this.amount / 1000)
  75. }
  76. function buyService() {
  77. if (!this.url) {
  78. document.getElementById('overlay-error').textContent = "You must provide a URL."
  79. return
  80. } else if (Math.ceil(this.cost > this.credits)) {
  81. document.getElementById('overlay-error').textContent =
  82. 'Insuficient Credits'
  83. return
  84. }
  85. this.paying = true
  86. let note = ''
  87. let country = document.getElementById('country')
  88. if (country) {
  89. note = JSON.stringify({'location': country.value})
  90. }
  91. fetch('/panel/orders', {
  92. method: 'POST',
  93. headers: {'Content-Type': 'application/json',
  94. 'Accept': 'application/json',
  95. 'X-XSRF-TOKEN': this.token},
  96. body: JSON.stringify({'service': this.selected.id,
  97. 'quantity': this.amount, 'url': this.url, 'note': note}), }).then(
  98. response => {
  99. if (response.ok) {
  100. document.getElementById('overlay-error').textContent = `Success!`
  101. this.completed = true
  102. this.$emit('updateUser')
  103. this.$emit('updateOrders')
  104. } else if (response.status == 520) {
  105. document.getElementById('overlay-error').textContent =
  106. 'Insuficient Credits'
  107. } else {
  108. document.getElementById('overlay-error').textContent = `Error
  109. ${response.status}: ${response.statusText}`
  110. }
  111. this.paying = false
  112. }
  113. )
  114. }
  115. function page() {
  116. switch (this.active) {
  117. case '#new-order':
  118. return 'new-order'
  119. case '#credits':
  120. return 'credits'
  121. }
  122. console.log(this.active)
  123. }
  124. export default {
  125. data() {
  126. return {servicePane: true, services: null, selected: null, amount: 0,
  127. paying: false, url: '', completed: false}
  128. },
  129. components: {ServicePane, Loading, Credits},
  130. props: ['token', 'credits', 'active'],
  131. created() {
  132. fetch("/panel/services", {
  133. method: 'GET',
  134. headers: {'Content-Type': 'application/json',
  135. 'Accept': 'application/json',
  136. 'X-XSRF-TOKEN': this.token}
  137. }).then(response => {
  138. response.json().then(data => {this.services = data})
  139. })
  140. },
  141. methods: {select, buyService},
  142. computed: {cost, page},
  143. emits: ['updateUser', 'updateOrders']
  144. }
  145. </script>