index.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. <template>
  2. <ele-page flex-table>
  3. <book-search @search="reload" />
  4. <common-table
  5. ref="pageRef"
  6. :pageConfig="pageConfig"
  7. :columns="columns"
  8. :datasource="datasource"
  9. :tools="false"
  10. >
  11. <template #toolbar>
  12. <el-radio-group @change="handleStatusChange" v-model="searchType">
  13. <el-radio-button label="全部" value="0" />
  14. <el-radio-button label="已加入回收书单(正在回收)" value="1" />
  15. <el-radio-button label="已加入回收书单(暂停回收)" value="2" />
  16. </el-radio-group>
  17. <span class="ml-8"></span>
  18. <el-button type="danger" plain v-permission="'recycle:independent:batchAddBlacklist'" @click="onBlacklist()">加黑名单</el-button>
  19. <el-button type="warning" plain v-permission="'recycle:independent:batchPauseRecycle'" @click="onRecycle(null, 2)">暂停回收</el-button>
  20. <el-button type="warning" plain v-permission="'recycle:independent:batchStartRecycle'" @click="onRecycle(null, 1)">开启回收</el-button>
  21. <el-button type="success" plain v-permission="'recycle:independent:batchAddSocial'" @click="onType(1)">加社科库</el-button>
  22. <el-button type="primary" plain v-permission="'recycle:independent:batchAddTeach'" @click="onType(2)">加教材库</el-button>
  23. </template>
  24. <template #cover="{ row }">
  25. <el-image
  26. style="width: 90px; height: 120px; border-radius: 4px"
  27. fit="cover"
  28. :src="row.cover"
  29. :preview-src-list="row.cover ? [row.cover] : []"
  30. :initial-index="0"
  31. preview-teleported
  32. />
  33. </template>
  34. <template #baseInfo="{ row }">
  35. <book-info :row="row" @refresh="reload" />
  36. </template>
  37. <template #subscribeNum="{ row }">
  38. <el-link type="primary" @click="handleDetail(row)">
  39. {{ row.subscribeNum ?? 0 }}
  40. </el-link>
  41. </template>
  42. <template #view="{ row }">
  43. <div class="grid grid-cols-2 gap-2 book-btns">
  44. <el-button
  45. color="#951d1d"
  46. @click="handleViewUrl(row, 'kw')"
  47. v-permission="'recycle:independent:viewUrl'"
  48. >
  49. 查看孔网
  50. </el-button>
  51. <el-button
  52. color="#e99d42"
  53. @click="onRecycleLog(row)"
  54. v-permission="'recycle:independent:viewRecycleLog'"
  55. >
  56. 回收日志
  57. </el-button>
  58. <el-button
  59. color="#f27606"
  60. @click="handleViewUrl(row, 'tb')"
  61. v-permission="'recycle:independent:viewUrl'"
  62. >
  63. 查看淘宝
  64. </el-button>
  65. <el-button color="#0f7dc7" v-permission="'recycle:independent:viewSalesLog'" @click="onSalesLog(row)">
  66. 售价日志
  67. </el-button>
  68. <el-button color="#399420" @click="handleViewUrl(row, 'db')">
  69. 查看豆瓣
  70. </el-button>
  71. <el-button
  72. color="#a4adb3"
  73. @click="handleViewUrl(row, 'dd')"
  74. v-permission="'recycle:independent:viewUrl'"
  75. >
  76. 查看当当
  77. </el-button>
  78. </div>
  79. </template>
  80. <template #action="{ row }">
  81. <row-actions :row="row" @discount="onDiscount" @blacklist="onBlacklist" @max="onMax" @recycle="onRecycle" @order="onOrder" @remove="onRemove" />
  82. </template>
  83. </common-table>
  84. <arrival-dialogs ref="dialogsRef" @refresh="reload" />
  85. </ele-page>
  86. </template>
  87. <script setup>
  88. import { ref, reactive } from 'vue';
  89. import { dayjs } from 'element-plus';
  90. import CommonTable from '@/components/CommonPage/CommonTable.vue';
  91. import bookSearch from '@/views/data/arrivalStats/components/page-search.vue';
  92. import bookInfo from '@/views/recycle/components/book-info.vue';
  93. import rowActions from './components/row-actions.vue';
  94. import arrivalDialogs from './components/arrival-dialogs.vue';
  95. import { initArrivalHandlers, onDiscount, onBlacklist, onMax, onOrder, onRecycle, onRemove, onRecycleLog, onSalesLog, onType } from './components/handlers.js';
  96. import request from '@/utils/request';
  97. defineOptions({ name: 'ArrivalStats' });
  98. const searchType = ref('0');
  99. const pageRef = ref(null);
  100. const dialogsRef = ref(null);
  101. initArrivalHandlers(pageRef, dialogsRef, () => pageRef.value?.reload());
  102. function formatTime(value) {
  103. if (!value) {
  104. return '-';
  105. }
  106. const date = dayjs(value);
  107. return date.isValid() ? date.format('YYYY-MM-DD HH:mm:ss') : value;
  108. }
  109. /** 表格列配置 */
  110. const columns = ref([
  111. {
  112. type: 'selection',
  113. columnKey: 'selection',
  114. width: 50,
  115. align: 'center',
  116. fixed: 'left'
  117. },
  118. {
  119. label: '图片',
  120. prop: 'cover',
  121. width: 120,
  122. slot: 'cover',
  123. align: 'center'
  124. },
  125. {
  126. label: '信息',
  127. prop: 'baseInfo',
  128. minWidth: 480,
  129. slot: 'baseInfo'
  130. },
  131. {
  132. label: '订阅次数',
  133. prop: 'subscribeNum',
  134. slot: 'subscribeNum',
  135. sortable: true,
  136. columnKey: 'subscribeNum',
  137. minWidth: 120,
  138. align: 'center'
  139. },
  140. {
  141. label: '最大回收量',
  142. prop: 'recycleMax',
  143. minWidth: 110,
  144. align: 'center'
  145. },
  146. {
  147. label: '最近一次订阅时间',
  148. prop: 'lastSubscribeTime',
  149. sortable: true,
  150. columnKey: 'lastSubscribeTime',
  151. minWidth: 180,
  152. align: 'center',
  153. formatter: (row) => formatTime(row.lastSubscribeTime)
  154. },
  155. {
  156. label: '查看',
  157. prop: 'view',
  158. slot: 'view',
  159. width: 234,
  160. fixed: 'right'
  161. },
  162. {
  163. columnKey: 'action',
  164. label: '操作',
  165. width: 234,
  166. slot: 'action',
  167. fixed: 'right'
  168. }
  169. ]);
  170. const pageConfig = reactive({
  171. pageUrl: '/shop/shopNoticeArrival/statPage',
  172. fileName: '到货提醒统计',
  173. cacheKey: 'arrivalStatsTable',
  174. rowKey: 'isbn',
  175. params: { searchType: '0' }
  176. });
  177. const datasource = ({ pages, where, orders, sorter }) => {
  178. const pageNum = Number(pages?.pageNum || 1);
  179. const pageSize = Number(pages?.pageSize || 10);
  180. const params = {
  181. ...(pageConfig.params || {}),
  182. ...where,
  183. offset: (pageNum - 1) * pageSize,
  184. limitSize: pageSize
  185. };
  186. if (orders?.orderByColumn) {
  187. params.orderType = sorter?.column?.columnKey || orders.orderByColumn;
  188. params.orderWay = orders.isAsc === 'ascending' ? 'asc' : 'desc';
  189. }
  190. return request
  191. .get('/shop/shopNoticeArrival/statPage', { params })
  192. .then((res) => {
  193. if (res.data.code === 200) {
  194. return res.data;
  195. }
  196. return Promise.reject(new Error(res.data.msg));
  197. });
  198. };
  199. function handleStatusChange(value) {
  200. searchType.value = value;
  201. pageConfig.params.searchType = value;
  202. pageRef.value?.reload();
  203. }
  204. function reload(where) {
  205. pageRef.value?.reload(where);
  206. }
  207. function handleDetail(row) {
  208. dialogsRef.value?.openDetail(row);
  209. }
  210. const handleViewUrl = (row, type) => {
  211. let url = '';
  212. if (type == 'dd') {
  213. url = `https://search.dangdang.com/?key=${row.isbn}&act=input`;
  214. } else if (type == 'tb') {
  215. url = `https://s.taobao.com/search?page=1&q=${row.isbn}&sort=sale-desc&tab=all`;
  216. } else if (type == 'db') {
  217. url = `https://search.douban.com/book/subject_search?search_text=${row.isbn}`;
  218. } else if (type == 'kw') {
  219. url = `https://search.kongfz.com/product_result/?key=${row.isbn}&status=0&_stpmt=eyJzZWFyY2hfdHlwZSI6ImFjdGl2ZSJ9`;
  220. }
  221. window.open(url, '_blank');
  222. };
  223. </script>
  224. <style lang="scss" scoped>
  225. .book-btns {
  226. gap: 6px;
  227. .el-button {
  228. min-width: 100px;
  229. font-size: 12px;
  230. color: #ffffff;
  231. padding: 4px 6px;
  232. margin-right: 0;
  233. }
  234. }
  235. </style>