ContentMedias.vue 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <template>
  2. <div class="ContentMedias">
  3. <q-linear-progress v-if="fetchLoading"
  4. indeterminate />
  5. <div v-if="canAddMedia && !readonly"
  6. class="q-mb-md">
  7. <entity-create ref="entityCreate"
  8. v-model:value="inputs"
  9. title="تعریف چند رسانه ای"
  10. :api="api"
  11. :entity-id-key="entityIdKey"
  12. :entity-param-key="entityParamKey"
  13. :show-close-button="false"
  14. :show-edit-button="false"
  15. :show-expand-button="false"
  16. :show-save-button="false"
  17. :show-reload-button="false" />
  18. <q-btn color="primary"
  19. class="full-width q-mt-md"
  20. :loading="entityCreateLoading"
  21. @click="entityCreate">
  22. افزودن چند رسانه ای
  23. </q-btn>
  24. </div>
  25. <media-category v-if="imageMedias.list.length > 0"
  26. :medias="imageMedias"
  27. icon="visibility"
  28. title="تصویر"
  29. class="q-mt-lg"
  30. :can-delete="canDelete"
  31. @onView="onView"
  32. @onDelete="onDelete" />
  33. <media-category v-if="soundMedias.list.length > 0"
  34. :medias="soundMedias"
  35. icon="mic_none"
  36. title="صوت"
  37. class="q-mt-lg"
  38. :can-delete="canDelete"
  39. @onView="onView"
  40. @onDelete="onDelete" />
  41. <media-category v-if="videoMedias.list.length > 0"
  42. :medias="videoMedias"
  43. icon="play_circle_outline"
  44. title="ویدیو"
  45. class="q-mt-lg"
  46. :can-delete="canDelete"
  47. @onView="onView"
  48. @onDelete="onDelete" />
  49. <media-category v-if="documentMedias.list.length > 0"
  50. :medias="documentMedias"
  51. icon="receipt_long"
  52. title="سند"
  53. class="q-mt-lg"
  54. :can-delete="canDelete"
  55. @onView="onView"
  56. @onDelete="onDelete" />
  57. </div>
  58. </template>
  59. <script>
  60. import { EntityCreate } from 'quasar-crud'
  61. import { APIGateway } from 'src/api/APIGateway.js'
  62. import { Media, MediaList } from 'src/models/Media.js'
  63. import { FormBuilderAssist } from 'quasar-form-builder'
  64. import MediaCategory from 'src/components/FormBuilderCustumComponents/ContentMedias/MediaCategory.vue'
  65. export default {
  66. name: 'ContentMedias',
  67. components: { MediaCategory, EntityCreate },
  68. props: {
  69. value: {
  70. default: () => [],
  71. type: [Array, String, Number, Boolean]
  72. },
  73. disable: {
  74. default: false,
  75. type: Boolean
  76. },
  77. canDelete: {
  78. type: Boolean,
  79. default: true
  80. },
  81. canAddMedia: {
  82. type: Boolean,
  83. default: true
  84. },
  85. sourceType: {
  86. type: String,
  87. default: 'CONTENT'
  88. },
  89. readonly: {
  90. default: false,
  91. type: Boolean
  92. },
  93. showPageLink: {
  94. default: true,
  95. type: Boolean
  96. },
  97. showDownloadLink: {
  98. default: false,
  99. type: Boolean
  100. }
  101. },
  102. emits: ['update:value'],
  103. data () {
  104. return {
  105. fetchLoading: false,
  106. medias: new MediaList(),
  107. api: APIGateway.media.APIAdresses.base,
  108. entityIdKey: 'id',
  109. entityParamKey: 'id',
  110. inputs: [
  111. { type: 'file', name: 'file', responseKey: 'file', label: 'فایل', placeholder: ' ', col: 'col-md-4 col-12' },
  112. { type: 'input', name: 'title', responseKey: 'title', label: 'عنوان', placeholder: ' ', col: 'col-md-4 col-12' },
  113. { type: 'select', name: 'type', responseKey: 'type', label: 'نوع', placeholder: ' ', options: (new Media()).typeEnums, col: 'col-md-4 col-12' },
  114. { type: 'input', name: 'url', responseKey: 'url', label: 'url', placeholder: ' ', col: 'col-12' },
  115. { type: 'input', name: 'iframe_code', responseKey: 'iframe_code', label: 'iframe_code', placeholder: ' ', col: 'col-12' },
  116. { type: 'input', name: 'script_code', responseKey: 'script_code', label: 'script_code', placeholder: ' ', col: 'col-12' },
  117. { type: 'hidden', name: 'source_type', responseKey: 'source_type', value: 'CONTENT' }
  118. ],
  119. entityCreateLoading: false
  120. }
  121. },
  122. computed: {
  123. videoMedias () {
  124. return new MediaList(this.medias.getType('VIDEO'))
  125. },
  126. soundMedias () {
  127. return new MediaList(this.medias.getType('SOUND'))
  128. },
  129. imageMedias () {
  130. return new MediaList(this.medias.getType('IMAGE'))
  131. },
  132. documentMedias () {
  133. return new MediaList(this.medias.getType('DOCUMENT'))
  134. }
  135. },
  136. watch: {
  137. value: {
  138. handler () {
  139. this.inputData = this.value
  140. if (this.value.length > 0 && this.value[0].id) {
  141. this.medias = new MediaList(this.value)
  142. this.$emit('update:value', this.medias.list.map(item => item.id))
  143. }
  144. },
  145. immediate: true
  146. }
  147. },
  148. created () {
  149. FormBuilderAssist.setAttributeByName(this.inputs, 'source_type', 'value', this.sourceType)
  150. this.inputData = this.value
  151. },
  152. methods: {
  153. onView (media) {
  154. if (this.showPageLink) {
  155. const routeData = this.$router.resolve({ name: 'Admin.Media.Show', params: { id: media.id } })
  156. window.open(routeData.href, '_blank')
  157. return
  158. }
  159. if (this.showDownloadLink) {
  160. const source = media.file || media.url
  161. if (!source) {
  162. return
  163. }
  164. const fileName = (source.match(/(?<=\/)[^/?#]+(?=[^/]*$)/gm) || [media.title])[0]
  165. this.fetchLoading = true
  166. fetch(source)
  167. .then(response => response.blob())
  168. .then(blob => {
  169. const link = document.createElement('a')
  170. link.href = URL.createObjectURL(blob)
  171. link.download = fileName
  172. link.click()
  173. this.fetchLoading = false
  174. })
  175. .catch(() => {
  176. this.fetchLoading = false
  177. })
  178. }
  179. },
  180. onDelete (media) {
  181. this.removeMedia(media.id)
  182. },
  183. removeMedia (mediaId) {
  184. const mediaIndex = this.medias.list.findIndex(item => item.id === mediaId)
  185. if (mediaIndex === -1) {
  186. return
  187. }
  188. this.medias.list.splice(mediaIndex, 1)
  189. this.$emit('update:value', this.medias.list.map(item => item.id))
  190. },
  191. entityCreate () {
  192. this.entityCreateLoading = true
  193. this.$refs.entityCreate.createEntity(false)
  194. .then(response => {
  195. this.medias.list.push(new Media(response.data))
  196. this.entityCreateLoading = false
  197. this.$emit('update:value', this.medias.list.map(item => item.id))
  198. })
  199. .catch(() => {
  200. this.entityCreateLoading = false
  201. })
  202. }
  203. }
  204. }
  205. </script>
  206. <style lang="scss" scoped>
  207. .ContentMedias {
  208. }
  209. </style>