Cover.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. <template>
  2. <div class="my-cover">
  3. <div class="operateBox" @click="dialogVisible = true">
  4. <span>选择素材</span>
  5. <!-- 负责展示父组件传过来的数据 -->
  6. <img :src="imgUrl" alt="" class="img">
  7. </div>
  8. <!-- 对话框 -->
  9. <el-dialog
  10. :append-to-body="true"
  11. :visible.sync="dialogVisible"
  12. width="720px">
  13. <el-card class="box-card">
  14. <div style="padding-bottom: 20px;">
  15. <el-radio-group v-model="collect" size="mini" @change="collectChange">
  16. <el-radio-button :label="false">全部</el-radio-button>
  17. <el-radio-button :label="true">收藏</el-radio-button>
  18. </el-radio-group>
  19. </div>
  20. <el-row :gutter="10">
  21. <el-col
  22. v-for="(image) in imageList"
  23. :key="image.id" class="img_item" :xs="12" :sm="6" :md="6" :lg="4">
  24. <div class="img_box" @click="selectImage(image)">
  25. <img :src="image.url" alt="">
  26. <!-- 当前点击项会展示小对勾
  27. v-show/v-if
  28. -->
  29. <div class="selected" v-show="image.selected">
  30. <img src="./img/selected.png" alt="">
  31. </div>
  32. </div>
  33. </el-col>
  34. </el-row>
  35. <el-pagination
  36. style="margin-top:10px;"
  37. background
  38. layout="sizes, prev, pager, next"
  39. :page-sizes="[5, 10, 15, 20]"
  40. :page-size="10"
  41. @current-change="currentChange"
  42. @size-change="sizeChange"
  43. :total="total_cont">
  44. </el-pagination>
  45. </el-card>
  46. <span slot="footer" class="dialog-footer">
  47. <el-button @click="cancel">取 消</el-button>
  48. <el-button type="primary" @click="confirm">确 定</el-button>
  49. </span>
  50. </el-dialog>
  51. </div>
  52. </template>
  53. <script>
  54. // 引入图片素材接口
  55. import { getImageList } from '@/api/image'
  56. export default {
  57. props: {
  58. imgUrl: {
  59. type: String
  60. }
  61. },
  62. data () {
  63. return {
  64. imageList: [], // 素材列表
  65. total_cont: 0, // 素材总数
  66. curPage: 1, // 当前要请求第几页数据
  67. per_page: 10, // 当前每页的条数
  68. dialogVisible: false, // 弹出框是否显示
  69. collect: false // 是否为收藏状态
  70. }
  71. },
  72. methods: {
  73. openDialog () {
  74. this.dialogVisible = true
  75. },
  76. currentChange (pageNum) {
  77. this.curPage = pageNum
  78. this.hGetImage()
  79. },
  80. // 发起素材请求列表
  81. hGetImage () {
  82. getImageList({
  83. collect: this.collect,
  84. per_page: this.per_page, // 每页的条数
  85. page: this.curPage // 当前请求第几页
  86. }).then(res => {
  87. // 素材列表
  88. // 处理源数据 在里面的每一项都添加一个字段 专门用来控制对勾是否显示
  89. // [{}{}{}] 完成映射关系的数组处理使用map函数
  90. this.imageList = res.data.data.results.map((item) => {
  91. return {
  92. ...item, // 把数组项中之前就有的三个字段展开放过来
  93. selected: false // false代表不展示 true代表展示
  94. }
  95. })
  96. this.total_cont = res.data.data.total_count
  97. })
  98. },
  99. sizeChange (pageSize) {
  100. this.per_page = pageSize
  101. this.hGetImage()
  102. },
  103. collectChange (collect) {
  104. this.hGetImage()
  105. },
  106. cancel () {
  107. this.dialogVisible = false
  108. },
  109. confirm () {
  110. // 遍历this.imageList找到seleted为true的那一项 取到它的url交给父组件
  111. let url = ''
  112. this.imageList.forEach((item) => {
  113. if (item.selected) {
  114. url = item.url
  115. }
  116. })
  117. // 交给父组件 这里是最关键的一部 不管中间经过什么样的交互
  118. this.$emit('update:imgUrl', url)
  119. this.dialogVisible = false
  120. },
  121. selectImage (image) {
  122. // 排它思想 selected
  123. // 把所有项都设置为false
  124. // 这个地方的选择并不是最终决定要将哪项抛给父组件 只有点击确定按钮才能决定
  125. // 点击确定按钮的时候需要去找当前身上有对勾的项然后把它的url拿到 交给父组件
  126. this.imageList.forEach((item) => {
  127. item.selected = false
  128. })
  129. // 把自己设置为true
  130. image.selected = true
  131. }
  132. },
  133. mounted () {
  134. this.hGetImage()
  135. }
  136. }
  137. </script>
  138. <style lang="less" scoped>
  139. .my-cover{
  140. display: inline-block;
  141. }
  142. .operateBox{
  143. display: inline-block;
  144. width: 100px;
  145. height: 100px;
  146. margin-left: 10px;
  147. border-radius: 4px;
  148. border:1px solid #ccc;
  149. font-size:13px;
  150. color:#666;
  151. text-align: center;
  152. line-height: 100px;
  153. overflow: hidden;
  154. cursor: pointer;
  155. position: relative;
  156. .img{
  157. position: absolute;
  158. top:0;
  159. left:0;
  160. width: 100%;
  161. height: 100%;
  162. }
  163. }
  164. .img_item {
  165. position: relative;
  166. box-sizing: border-box;
  167. .img_box{
  168. height: 120px;
  169. margin-bottom: 10px;
  170. position: relative;
  171. img{
  172. width: 100%;
  173. height: 100%;
  174. }
  175. .selected{
  176. position: absolute;
  177. width: 20%;
  178. left:0;
  179. top:0;
  180. }
  181. }
  182. }
  183. .option {
  184. position: absolute;
  185. left: 5px;
  186. right:5px;
  187. bottom: 5px;
  188. height: 30px;
  189. background: rgba(0, 0, 0, 0.3);
  190. color: #fff;
  191. display: flex;
  192. span {
  193. flex:1;
  194. text-align: center;
  195. cursor: pointer;
  196. line-height: 30px;
  197. }
  198. }
  199. .avatar-uploader-icon {
  200. font-size: 28px;
  201. color: #8c939d;
  202. width: 178px;
  203. height: 178px;
  204. line-height: 178px;
  205. text-align: center;
  206. }
  207. .uploadBox{
  208. text-align: center;
  209. img {
  210. width:100%;
  211. }
  212. // scoped代表当前的样式只能影响当前的组件 影响不了子组件的样式
  213. // 加上 /deep/ 之后可以进行深度样式控制
  214. // 当试图直接控制子组件内部元素样式的时候就需要添加 /deep/
  215. /deep/.el-upload {
  216. border: 1px dashed #d9d9d9;
  217. border-radius: 6px;
  218. cursor: pointer;
  219. position: relative;
  220. overflow: hidden;
  221. }
  222. }
  223. // 1.要复用 有多个地方都需要用到此组件
  224. // 2.维护性 .vue单文件代码行数不能太多
  225. // 组件的抽离必定增加组件之间的通信成本
  226. </style>