FarmDialog.vue 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <template>
  2. <custom-dialog :visible.sync="dialogVisible" title="我的农场" @close="onClose">
  3. <view class="farm-container">
  4. <view class="farm-grid">
  5. <view v-for="(plot, index) in plots" :key="index" class="farm-plot" @click="onPlotClick(index)">
  6. <view class="plot-content" :class="getPlotClass(plot)">
  7. <view v-if="plot.crop" class="crop-stage">
  8. <image :src="getCropImage(plot)" mode="aspectFit" class="crop-image"></image>
  9. </view>
  10. <view v-if="plot.weeds" class="weeds"></view>
  11. <view v-if="plot.needsWater" class="water-indicator"></view>
  12. </view>
  13. </view>
  14. </view>
  15. <view class="action-panel">
  16. <view class="action-buttons">
  17. <button @click="selectAction('plant')" :disabled="!canPlant">播种</button>
  18. <button @click="selectAction('water')" :disabled="!canWater">浇水</button>
  19. <button @click="selectAction('fertilize')" :disabled="!canFertilize">施肥</button>
  20. <button @click="selectAction('weed')" :disabled="!canWeed">除草</button>
  21. <button @click="selectAction('harvest')" :disabled="!canHarvest">收获</button>
  22. </view>
  23. <view class="selected-plot-info" v-if="selectedPlot !== null">
  24. <text>状态: {{ getPlotStatus(plots[selectedPlot]) }}</text>
  25. <text v-if="plots[selectedPlot].crop">作物: {{ plots[selectedPlot].crop.name }}</text>
  26. <text v-if="plots[selectedPlot].crop">生长进度: {{ getGrowthProgress(plots[selectedPlot]) }}%</text>
  27. </view>
  28. </view>
  29. </view>
  30. </custom-dialog>
  31. </template>
  32. <script>
  33. import CustomDialog from '@/components/CustomDialog/CustomDialog.vue'
  34. const CROPS = {
  35. carrot: {
  36. name: '胡萝卜',
  37. growthTime: 30, // minutes
  38. stages: ['/static/crops/carrot_stage1.png', '/static/crops/carrot_stage2.png', '/static/crops/carrot_stage3.png'],
  39. value: 100
  40. },
  41. tomato: {
  42. name: '番茄',
  43. growthTime: 60,
  44. stages: ['/static/crops/tomato_stage1.png', '/static/crops/tomato_stage2.png', '/static/crops/tomato_stage3.png'],
  45. value: 200
  46. }
  47. }
  48. export default {
  49. name: 'FarmDialog',
  50. components: {
  51. CustomDialog
  52. },
  53. props: {
  54. visible: {
  55. type: Boolean,
  56. default: false
  57. }
  58. },
  59. data() {
  60. return {
  61. dialogVisible: false,
  62. plots: Array(12).fill().map(() => ({
  63. crop: null,
  64. plantedAt: null,
  65. watered: false,
  66. fertilized: false,
  67. weeds: false,
  68. needsWater: false
  69. })),
  70. selectedPlot: null,
  71. selectedAction: null,
  72. growthTimer: null
  73. }
  74. },
  75. computed: {
  76. canPlant() {
  77. return this.selectedPlot !== null && !this.plots[this.selectedPlot].crop
  78. },
  79. canWater() {
  80. return this.selectedPlot !== null &&
  81. this.plots[this.selectedPlot].crop &&
  82. !this.plots[this.selectedPlot].watered
  83. },
  84. canFertilize() {
  85. return this.selectedPlot !== null &&
  86. this.plots[this.selectedPlot].crop &&
  87. !this.plots[this.selectedPlot].fertilized
  88. },
  89. canWeed() {
  90. return this.selectedPlot !== null &&
  91. this.plots[this.selectedPlot].weeds
  92. },
  93. canHarvest() {
  94. return this.selectedPlot !== null &&
  95. this.plots[this.selectedPlot].crop &&
  96. this.isCropReady(this.plots[this.selectedPlot])
  97. }
  98. },
  99. watch: {
  100. visible(newVal) {
  101. this.dialogVisible = newVal
  102. if (newVal) {
  103. this.startGrowthTimer()
  104. } else {
  105. this.stopGrowthTimer()
  106. }
  107. }
  108. },
  109. methods: {
  110. onClose() {
  111. this.$emit('update:visible', false)
  112. },
  113. onPlotClick(index) {
  114. this.selectedPlot = index
  115. if (this.selectedAction) {
  116. this.performAction(index)
  117. }
  118. },
  119. selectAction(action) {
  120. this.selectedAction = action
  121. },
  122. performAction(plotIndex) {
  123. const plot = this.plots[plotIndex]
  124. switch (this.selectedAction) {
  125. case 'plant':
  126. if (this.canPlant) {
  127. plot.crop = { ...CROPS.carrot }
  128. plot.plantedAt = Date.now()
  129. plot.watered = false
  130. plot.fertilized = false
  131. plot.weeds = false
  132. plot.needsWater = true
  133. }
  134. break
  135. case 'water':
  136. if (this.canWater) {
  137. plot.watered = true
  138. plot.needsWater = false
  139. }
  140. break
  141. case 'fertilize':
  142. if (this.canFertilize) {
  143. plot.fertilized = true
  144. }
  145. break
  146. case 'weed':
  147. if (this.canWeed) {
  148. plot.weeds = false
  149. }
  150. break
  151. case 'harvest':
  152. if (this.canHarvest) {
  153. // TODO: Add harvested items to inventory
  154. plot.crop = null
  155. plot.plantedAt = null
  156. plot.watered = false
  157. plot.fertilized = false
  158. plot.weeds = false
  159. plot.needsWater = false
  160. }
  161. break
  162. }
  163. this.selectedAction = null
  164. },
  165. getPlotClass(plot) {
  166. return {
  167. 'has-crop': plot.crop,
  168. 'needs-water': plot.needsWater,
  169. 'has-weeds': plot.weeds
  170. }
  171. },
  172. getCropImage(plot) {
  173. if (!plot.crop) return ''
  174. const growthStage = this.getGrowthStage(plot)
  175. return plot.crop.stages[growthStage]
  176. },
  177. getGrowthStage(plot) {
  178. if (!plot.crop || !plot.plantedAt) return 0
  179. const growthProgress = this.getGrowthProgress(plot)
  180. if (growthProgress >= 100) return 2
  181. if (growthProgress >= 50) return 1
  182. return 0
  183. },
  184. getGrowthProgress(plot) {
  185. if (!plot.crop || !plot.plantedAt) return 0
  186. const elapsed = (Date.now() - plot.plantedAt) / 1000 / 60 // minutes
  187. const progress = (elapsed / plot.crop.growthTime) * 100
  188. return Math.min(100, Math.floor(progress))
  189. },
  190. isCropReady(plot) {
  191. return this.getGrowthProgress(plot) >= 100
  192. },
  193. getPlotStatus(plot) {
  194. if (!plot.crop) return '空地'
  195. if (plot.weeds) return '需要除草'
  196. if (plot.needsWater) return '需要浇水'
  197. if (this.isCropReady(plot)) return '可以收获'
  198. return '生长中'
  199. },
  200. startGrowthTimer() {
  201. this.growthTimer = setInterval(() => {
  202. this.plots.forEach(plot => {
  203. if (plot.crop && !plot.watered) {
  204. plot.needsWater = true
  205. }
  206. if (plot.crop && Math.random() < 0.1) { // 10% chance to spawn weeds
  207. plot.weeds = true
  208. }
  209. })
  210. }, 60000) // Check every minute
  211. },
  212. stopGrowthTimer() {
  213. if (this.growthTimer) {
  214. clearInterval(this.growthTimer)
  215. this.growthTimer = null
  216. }
  217. }
  218. },
  219. beforeDestroy() {
  220. this.stopGrowthTimer()
  221. }
  222. }
  223. </script>
  224. <style lang="scss">
  225. @import './FarmDialog.scss';
  226. </style>