common-table.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. <template>
  2. <div class="common-table">
  3. <a-popconfirm :disabled="selectedRowKeys.length === 0" @confirm="onDelete">
  4. <template #title> <p>确认批量删除所选素材吗</p> </template
  5. ><a-button
  6. :disabled="selectedRowKeys.length === 0"
  7. style="margin-bottom: 10px"
  8. >批量删除</a-button
  9. >
  10. </a-popconfirm>
  11. <a-table
  12. bordered
  13. :data-source="list"
  14. :columns="columns"
  15. @change="getList"
  16. rowKey="id"
  17. :loading="loading"
  18. :pagination="tablePageOptions"
  19. :row-selection="{
  20. selectedRowKeys: selectedRowKeys,
  21. onChange: onSelectChange,
  22. }"
  23. >
  24. <template #video_name="{ record }">
  25. <div class="table-view-box">
  26. <div class="video-view" @click="onOpenPreview(record.url)">
  27. <i class="iconfont icon-ziyuan"></i>
  28. <img
  29. :src="
  30. record.url + '?x-oss-process=video/snapshot,t_0,f_jpg,m_fast'
  31. "
  32. alt=""
  33. />
  34. </div>
  35. <span>{{ record.name }}</span>
  36. </div>
  37. </template>
  38. <template #image_name="{ record }">
  39. <div class="table-view-box">
  40. <div class="image-view" @click="onOpenPreview(record.url)">
  41. <img :src="record.url" alt="" />
  42. </div>
  43. <span>{{ record.name }}</span>
  44. </div>
  45. </template>
  46. <template #duration="{ record }">{{ record.duration }}秒</template>
  47. <template #video_type="{ record }">
  48. <span v-show="record.video_type === 'S'">竖版视频</span>
  49. <span v-show="record.video_type === 'H'">横版视频</span>
  50. </template>
  51. <template #image_type="{ record }">
  52. <span v-show="record.image_type === 'S'">竖版大图</span>
  53. <span v-show="record.image_type === 'H'">横版大图</span>
  54. <span v-show="record.image_type === 'X'">小图</span>
  55. </template>
  56. <template #operation="{ record }">
  57. <a-button style="padding: 0" @click="onOpenPush(record)" type="link"
  58. >推送</a-button
  59. >
  60. <a-popconfirm
  61. @confirm="onDelete(record)"
  62. :disabled="Number(record.is_mine_uploaded) !== 1"
  63. >
  64. <template #title>
  65. <p>确认删除该素材吗</p>
  66. </template>
  67. <a-button
  68. :disabled="Number(record.is_mine_uploaded) !== 1"
  69. type="link"
  70. >删除</a-button
  71. >
  72. </a-popconfirm>
  73. </template>
  74. </a-table>
  75. <a-modal
  76. v-model:visible="pushVisible"
  77. :title="type === 'video' ? '推送视频' : '推送图片'"
  78. :confirmLoading="pushLoading"
  79. @ok="onConfirmPush"
  80. width="40%"
  81. >
  82. <span>选择广告主:</span>
  83. <a-cascader
  84. style="width: 360px"
  85. v-model:value="advertiser"
  86. :options="adList"
  87. placeholder="请选择"
  88. :field-names="{
  89. label: 'advertiser_name',
  90. value: 'advertiser_id',
  91. children: 'advertises',
  92. }"
  93. />
  94. </a-modal>
  95. <a-modal
  96. v-model:visible="previewVisible"
  97. width="40%"
  98. height="200px"
  99. :footer="null"
  100. :mask="true"
  101. wrapClassName="preview"
  102. style="max-height: 400px"
  103. >
  104. <img
  105. style="max-width: 100%; max-height: 100%"
  106. :src="currentUrl"
  107. alt=""
  108. v-show="type === 'picture'"
  109. />
  110. <video
  111. v-show="type === 'video'"
  112. style="max-width: 100%; max-height: 100%"
  113. :src="currentUrl"
  114. controls
  115. ></video>
  116. </a-modal>
  117. <preview-box
  118. @close="previewVisible = false"
  119. :type="type"
  120. :url="currentUrl"
  121. v-if="previewVisible"
  122. ></preview-box>
  123. </div>
  124. </template>
  125. <script lang="ts">
  126. import usePagination from "@/hooks/usePagination";
  127. import PreviewBox from "./preview.vue";
  128. import {
  129. defineComponent,
  130. reactive,
  131. toRefs,
  132. ref,
  133. watchEffect,
  134. watch,
  135. } from "vue";
  136. import {
  137. TableColumnOfVideo,
  138. TableColumnOfImage,
  139. } from "../../_pageOptions/table_material";
  140. //getPromotionList
  141. import {
  142. getVideoList,
  143. getImageList,
  144. deleteVideo,
  145. deleteImage,
  146. getAdvertiser,
  147. pushMaterial,
  148. } from "@/api";
  149. import { message } from "ant-design-vue";
  150. const CommonTable = defineComponent({
  151. components: { PreviewBox },
  152. props: ["materialType", "searchForm"],
  153. setup(props) {
  154. let { meta, tablePageOptions } = usePagination();
  155. const state = reactive({
  156. type: "",
  157. loading: false,
  158. list: ref<any[]>([]),
  159. columns: ref<any[]>([]),
  160. adList: ref<any[]>([]),
  161. selectedRowKeys: ref<any[]>([]),
  162. pushVisible: false,
  163. currentId: 0, // 当前操作的素材id
  164. advertiser: ref<string[]>([]), // 选择的广告主
  165. previewVisible: false,
  166. currentUrl: "",
  167. pushLoading: false,
  168. });
  169. const getList = async (page?: any) => {
  170. state.loading = true;
  171. // return message.success("请求接口");
  172. let api = state.type === "video" ? getVideoList : getImageList;
  173. let { data } = await api({
  174. page: page ? page.current : 1,
  175. ...props.searchForm,
  176. });
  177. state.loading = false;
  178. state.list = data.list;
  179. meta.value = data.meta;
  180. };
  181. // 列表选项改变
  182. const onSelectChange = (selectedRowKeys: any) => {
  183. state.selectedRowKeys = selectedRowKeys;
  184. };
  185. watch(
  186. () => props.searchForm,
  187. (oldVal, newVal) => {
  188. getList({ current: 1 });
  189. state.selectedRowKeys = [];
  190. }
  191. );
  192. return { ...toRefs(state), tablePageOptions, getList, onSelectChange };
  193. },
  194. mounted() {
  195. this.type = this.$props.materialType;
  196. if (this.type === "video") this.columns = TableColumnOfVideo;
  197. if (this.type === "picture") this.columns = TableColumnOfImage;
  198. this.getAdList();
  199. },
  200. methods: {
  201. // 获取广告主列表
  202. async getAdList() {
  203. let { data } = await getAdvertiser();
  204. this.adList = data;
  205. if (this.adList.length === 0) return;
  206. this.adList.forEach((item) => {
  207. item.advertiser_id = item.account_id;
  208. item.advertiser_name = item.account_name;
  209. });
  210. this.selectedRowKeys = [];
  211. console.log("LIST", this.selectedRowKeys);
  212. },
  213. async onDelete(val?: any) {
  214. let arr = [];
  215. if (val.id) {
  216. // 单个删除
  217. arr.push(val.id);
  218. } else {
  219. // 多选删除
  220. arr = this.selectedRowKeys;
  221. }
  222. let ids = arr.join(",");
  223. console.log("删除", val);
  224. let api = this.type === "video" ? deleteVideo : deleteImage;
  225. try {
  226. await api({ ids });
  227. message.success("删除成功");
  228. } catch (err) {
  229. message.error("删除失败");
  230. console.log("ERR:", err);
  231. } finally {
  232. this.getList({ current: 1 });
  233. this.selectedRowKeys = [];
  234. }
  235. },
  236. // 点击推送
  237. onOpenPush(item: any) {
  238. this.currentId = item.id;
  239. this.advertiser = [];
  240. this.pushVisible = true;
  241. this.pushLoading = false;
  242. },
  243. // 确定推送
  244. async onConfirmPush() {
  245. this.pushLoading = true;
  246. console.log("IDS", this.currentId, this.advertiser);
  247. try {
  248. await pushMaterial({
  249. material_id: this.currentId,
  250. advertiser_id: this.advertiser[1],
  251. });
  252. this.pushVisible = false;
  253. message.success("推送成功");
  254. } catch (err) {
  255. this.pushVisible = false;
  256. message.error("推送失败");
  257. console.log(err);
  258. } finally {
  259. this.pushLoading = false;
  260. }
  261. },
  262. // 点击预览
  263. onOpenPreview(url: string) {
  264. this.currentUrl = url;
  265. this.previewVisible = true;
  266. },
  267. },
  268. //https://firemanage.oss-cn-hangzhou.aliyuncs.com/material/video/S-20210739163739-E9XA.mp4?x-oss-process=video/snapshot,t_0,f_jpg,m_fast
  269. });
  270. export default CommonTable;
  271. </script>
  272. <style lang="scss" scoped>
  273. @import "@/assets/common-style/frame.scss";
  274. .common-table {
  275. background: white;
  276. padding: 10px;
  277. .table-view-box {
  278. display: flex;
  279. align-items: center;
  280. cursor: pointer;
  281. .video-view {
  282. width: 80px;
  283. height: 60px;
  284. border: 1px solid gray;
  285. margin-right: 4px;
  286. position: relative;
  287. display: flex;
  288. align-items: center;
  289. justify-content: center;
  290. background: rgb(94, 93, 93);
  291. img {
  292. max-width: 58px;
  293. max-height: 58px;
  294. }
  295. .icon-ziyuan {
  296. position: absolute;
  297. top: 18px;
  298. left: 32px;
  299. color: white;
  300. }
  301. }
  302. .image-view {
  303. width: 60px;
  304. height: 60px;
  305. border: 1px solid gray;
  306. margin-right: 4px;
  307. display: flex;
  308. justify-content: center;
  309. align-items: center;
  310. img {
  311. max-width: 58px;
  312. max-height: 58px;
  313. }
  314. }
  315. // &:hover span {
  316. // color: rgb(0, 140, 255);
  317. // }
  318. }
  319. }
  320. </style>