main_panel.svelte 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <script lang="js">
  2. import CardThumb from './card_thumb.svelte';
  3. import { deck, setDeck, deckOps, format, setFormat } from '../deck';
  4. import { cardLimit } from '../card_db';
  5. import {
  6. parseYdk,
  7. genYdk,
  8. genYdke,
  9. downloadStringAsFile,
  10. } from '../utils';
  11. let fileInput;
  12. function openDeck() {
  13. fileInput.click();
  14. }
  15. function loadDeck(event) {
  16. const file = event.target.files[0];
  17. if (file) {
  18. const reader = new FileReader();
  19. reader.onload = (event) => {
  20. let content = event.target.result;
  21. setDeck(parseYdk(content));
  22. };
  23. reader.readAsText(file);
  24. }
  25. }
  26. function clearDeck() {
  27. setDeck({
  28. 'main': [],
  29. 'extra': [],
  30. 'side': [],
  31. });
  32. }
  33. function saveDeck() {
  34. let deckString = genYdk($deck);
  35. downloadStringAsFile(deckString)
  36. }
  37. function copyDeck() {
  38. let deckString = genYdk($deck);
  39. navigator.clipboard.writeText(deckString)
  40. .then(() => {
  41. alert('YDK卡组码已复制到剪贴板');
  42. })
  43. .catch(err => {
  44. alert("失败!");
  45. });
  46. }
  47. function shareDeck() {
  48. let url = window.location.href;
  49. url = url.split('#')[0]
  50. url = url + '#' + genYdke($deck);
  51. navigator.clipboard.writeText(url)
  52. .then(() => {
  53. alert('分享链接已复制到剪贴板');
  54. })
  55. .catch(err => {
  56. alert("失败!");
  57. });
  58. }
  59. function onDrop(to, event, targetIdx) {
  60. event.preventDefault();
  61. event.stopPropagation();
  62. const data = JSON.parse(event.dataTransfer.getData('text'));
  63. let from = data.area;
  64. if (from === 'search') {
  65. if (to === 'main') {
  66. deckOps.add2main(data.id, targetIdx);
  67. } else if (to === 'side') {
  68. deckOps.add2side(data.id, targetIdx);
  69. } else if (to === 'extra') {
  70. deckOps.add2extra(data.id, targetIdx);
  71. }
  72. } else {
  73. deckOps.move(from, to, data.idx, targetIdx);
  74. }
  75. }
  76. </script>
  77. <input bind:this={fileInput} style="display:none;" onchange={loadDeck} type="file" class="file-input" accept=".ydk" />
  78. <div class="middle-panel">
  79. <div class="control-bar">
  80. <button class="btn" onclick={openDeck}>打开</button>
  81. <button class="btn" onclick={saveDeck}>保存</button>
  82. <button class="btn" onclick={clearDeck}>清空</button>
  83. <button class="btn" onclick={copyDeck}>复制到剪贴板</button>
  84. <button class="btn" onclick={shareDeck}>分享</button>
  85. <select bind:value={$format} class="select-format" id="format" onchange={()=>setFormat($format)}>
  86. <option value="none">无禁限</option>
  87. <option value="ocg">OCG</option>
  88. <option value="tcg">TCG</option>
  89. <option value="md">大师决斗</option>
  90. <option value="cnocg">简中</option>
  91. </select>
  92. </div>
  93. <div class="deck-section">
  94. <div class="deck-group">
  95. <h3>主卡组({$deck.main.length})</h3>
  96. <div role="region" ondragover={(e)=>e.preventDefault()} ondrop={(e)=>onDrop("main", e, -1)} class="card-grid main-deck">
  97. {#each $deck.main as card, i}
  98. <div class="card-grid-thumb" role="region" ondragover={(e)=>e.preventDefault()} ondrop={(e)=>onDrop("main", e, i)}>
  99. <CardThumb id={card} idx={i} area="main" limitNum={cardLimit(card, $format)} />
  100. </div>
  101. {/each}
  102. </div>
  103. </div>
  104. <div class="deck-group">
  105. <h3>额外卡组({$deck.extra.length})</h3>
  106. <div role="region" ondragover={(e)=>e.preventDefault()} ondrop={(e)=>onDrop("extra", e, -1)} class="card-grid extra-deck">
  107. {#each $deck.extra as card, i}
  108. <div class="card-grid-thumb" role="region" ondragover={(e)=>e.preventDefault()} ondrop={(e)=>onDrop("extra", e, i)}>
  109. <CardThumb id={card} idx={i} area="extra" limitNum={cardLimit(card, $format)} />
  110. </div>
  111. {/each}
  112. </div>
  113. </div>
  114. <div class="deck-group">
  115. <h3>副卡组({$deck.side.length})</h3>
  116. <div role="region" ondragover={(e)=>e.preventDefault()} ondrop={(e)=>onDrop("side", e, -1)} class="card-grid side-deck">
  117. {#each $deck.side as card, i}
  118. <div class="card-grid-thumb" role="region" ondragover={(e)=>e.preventDefault()} ondrop={(e)=>onDrop("side", e, i)}>
  119. <CardThumb id={card} idx={i} area="side" limitNum={cardLimit(card, $format)} />
  120. </div>
  121. {/each}
  122. </div>
  123. </div>
  124. </div>
  125. </div>
  126. <style>
  127. .middle-panel {
  128. width: 55%;
  129. padding: 20px;
  130. background-color: #fff;
  131. overflow-y: auto;
  132. }
  133. @media screen and (max-width: 768px) {
  134. .middle-panel {
  135. width: 100%;
  136. }
  137. }
  138. .control-bar {
  139. margin-bottom: 20px;
  140. }
  141. .btn {
  142. padding: 8px 20px;
  143. margin-right: 10px;
  144. background-color: #4CAF50;
  145. color: white;
  146. border: none;
  147. border-radius: 4px;
  148. cursor: pointer;
  149. }
  150. .select-format {
  151. padding: 8px 8px;
  152. margin-right: 10px;
  153. cursor: pointer;
  154. font-size: 1.1em;
  155. }
  156. .deck-group {
  157. margin-bottom: 30px;
  158. }
  159. .deck-group h3 {
  160. margin-bottom: 10px;
  161. color: #333;
  162. }
  163. .card-grid {
  164. display: grid;
  165. grid-template-columns: repeat(auto-fill, minmax(52px, 1fr));
  166. grid-auto-flow: dense;
  167. overflow-y: auto;
  168. padding: 10px;
  169. border: 1px solid #ddd;
  170. border-radius: 4px;
  171. min-height: 80px;
  172. }
  173. .card-grid-thumb {
  174. position: relative;
  175. aspect-ratio: 1/1.4;
  176. border-radius: 5px;
  177. }
  178. </style>