list.vue 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. <template>
  2. <div class="page-indent-list">
  3. <el-form
  4. ref="searchForm"
  5. :inline="true"
  6. :model="form"
  7. label-width="110px"
  8. >
  9. <div class="flex flex-wrap items-center search-form">
  10. <el-form-item :label="$t(prefix + 'label_project_name') + ':'">
  11. <el-input v-model="form.name"></el-input>
  12. </el-form-item>
  13. <el-form-item :label="$t(prefix + 'label_category') + ':'">
  14. <el-cascader
  15. v-model="form.category"
  16. :options="categoryList"
  17. :props="{ label: 'name', value: 'id' }"
  18. ></el-cascader>
  19. </el-form-item>
  20. <el-form-item :label="$t(prefix + 'label_status') + ':'">
  21. <el-select
  22. v-model="form.status"
  23. clearable
  24. >
  25. <el-option
  26. v-for="item in statusList"
  27. :key="item.value"
  28. :label="item.label"
  29. :value="item.value"
  30. ></el-option>
  31. </el-select>
  32. </el-form-item>
  33. <div class="flex items-center btn-group">
  34. <el-button
  35. size="small"
  36. type="primary"
  37. @click="search"
  38. >
  39. {{ $t('btn_query') }}
  40. </el-button>
  41. <el-button
  42. size="small"
  43. type="default"
  44. @click="reset"
  45. >
  46. {{ $t('btn_reset') }}
  47. </el-button>
  48. </div>
  49. </div>
  50. </el-form>
  51. <div style="margin-bottom: 12px">
  52. <el-button
  53. size="small"
  54. type="primary"
  55. @click="componentEditVisible = 1"
  56. >
  57. {{ $t('btn_add') }}
  58. </el-button>
  59. </div>
  60. <el-table
  61. ref="tableIndent"
  62. :header-cell-style="{ backgroundColor: '#F2F6FC' }"
  63. :row-style="{ backgroundColor: '#F2F6FC' }"
  64. :data="list"
  65. default-expand-all
  66. border
  67. >
  68. <el-table-column type="index"></el-table-column>
  69. <el-table-column
  70. v-for="value in mainTableConfig as any[]"
  71. :key="value.field"
  72. :align="value.align || 'center'"
  73. :width="value.width || ''"
  74. :prop="value.field"
  75. :label="$t(value.label)"
  76. >
  77. <template #default="scope">
  78. <div v-if="value.type === 'imageList'">
  79. <img
  80. v-if="scope.row[value.field].length"
  81. style="width: 100%"
  82. :src="scope.row[value.field][0]"
  83. alt=""
  84. />
  85. </div>
  86. <div v-else-if="value.field === 'status'">
  87. <div>
  88. {{ getStatusLabel(scope.row[value.field]) }}
  89. </div>
  90. <el-button
  91. size="small"
  92. type="primary"
  93. link
  94. @click="openRecord(scope.row)"
  95. >
  96. {{ $t(prefix + 'label_audit_detail') }}
  97. </el-button>
  98. </div>
  99. <div
  100. v-else
  101. class="table-cell-content"
  102. :style="value.style || {}"
  103. >
  104. {{ scope.row[value.field] }}
  105. </div>
  106. </template>
  107. </el-table-column>
  108. <el-table-column
  109. prop="status"
  110. width="220"
  111. :label="$t('table_operation')"
  112. >
  113. <template #default="scope">
  114. <el-button
  115. size="small"
  116. type="primary"
  117. :disabled="scope.row.status === 0"
  118. @click="edit(scope.row)"
  119. >
  120. {{ $t('btn_edit') }}
  121. </el-button>
  122. <el-button
  123. size="small"
  124. type="warning"
  125. :disabled="scope.row.status !== 0"
  126. @click="examine(scope.row)"
  127. >
  128. {{ $t('btn_audit') }}
  129. </el-button>
  130. <el-button
  131. :disabled="scope.row.status !== 2"
  132. size="small"
  133. type="danger"
  134. @click="deleteProductFunc(scope.row)"
  135. >
  136. {{ $t('btn_delete') }}
  137. </el-button>
  138. </template>
  139. </el-table-column>
  140. </el-table>
  141. <el-pagination
  142. v-show="total > 0"
  143. v-model:page="pageForm.page"
  144. v-model:limit="pageForm.limit"
  145. :total="total"
  146. @pagination="getList"
  147. />
  148. <comp-edit
  149. v-model:visible="componentEditVisible"
  150. :product-data="dataForEdit"
  151. :category-data="categoryList"
  152. @update:visible="getList"
  153. ></comp-edit>
  154. <comp-record
  155. :id="recordId"
  156. v-model:visible="componentRecordVisible"
  157. :status-list="statusList"
  158. ></comp-record>
  159. <comp-examine
  160. v-model:visible="componentExamineVisible"
  161. :category-data="categoryList"
  162. :data-for-examine="dataForEaxmine"
  163. @update:visible="getList"
  164. ></comp-examine>
  165. </div>
  166. </template>
  167. <script lang="ts" setup>
  168. import { defineComponent, ref } from 'vue'
  169. import {
  170. ElButton,
  171. ElForm,
  172. ElFormItem,
  173. ElInput,
  174. ElTable,
  175. ElTableColumn,
  176. ElSelect,
  177. ElOption,
  178. ElMessageBox,
  179. ElNotification,
  180. ElPagination,
  181. ElCascader,
  182. } from 'element-plus'
  183. import compEdit from './components/edit.vue'
  184. import compRecord from './components/record.vue'
  185. import compExamine from './components/examine.vue'
  186. import { $t } from '@/i18n/index'
  187. import { getProductList, deleteProduct } from '@/api/product.js'
  188. import { getCategoryTree } from '@/api/indent.js'
  189. defineComponent({
  190. name: 'ComponentIndentProductList',
  191. })
  192. // 用来对oss的图片、视频等媒体数据的url进行匹配替换
  193. const $mediaRegExp = /^(https?:)?\/\/.+(.com.au\/|.com\/)/
  194. const prefix = 'order.product.'
  195. let componentEditVisible = ref(0) // 1 新增, 2编辑. 0关闭
  196. let componentRecordVisible = ref(false) // 审核记录
  197. let componentExamineVisible = ref(false) // 审核
  198. let dataForEaxmine = ref({})
  199. let dataForEdit = ref({}) // 修改时用, 只是用作传递给子组件数据的变量
  200. let recordId = ref('')
  201. let loading = ref(false)
  202. let categoryList = ref([])
  203. let form = ref({
  204. name: '',
  205. category: [],
  206. status: '',
  207. } as any)
  208. let total = ref(0)
  209. let pageForm = ref({
  210. page: 1,
  211. limit: 20,
  212. })
  213. let list = ref([])
  214. const mainTableConfig = [
  215. {
  216. label: 'order.product.label_img',
  217. type: 'imageList',
  218. field: 'images',
  219. width: '120',
  220. },
  221. {
  222. label: 'order.product.label_product_code',
  223. field: 'product_sku',
  224. width: '180',
  225. },
  226. {
  227. label: 'order.product.label_name',
  228. field: 'product_name',
  229. // style: 'text-align: left'
  230. },
  231. {
  232. label: 'order.product.label_status',
  233. field: 'status',
  234. width: '110',
  235. style: 'font-weight: bold;',
  236. },
  237. {
  238. label: 'table_operator',
  239. field: 'admin_name',
  240. width: '90',
  241. },
  242. {
  243. label: 'table_operated_time',
  244. field: 'update_time',
  245. width: '180',
  246. },
  247. ]
  248. const statusList = [
  249. {
  250. value: 0,
  251. label: '待审核',
  252. },
  253. {
  254. value: 1,
  255. label: '审核通过',
  256. },
  257. {
  258. value: 2,
  259. label: '审核不通过',
  260. },
  261. ]
  262. const search = () => {
  263. pageForm.value = {
  264. page: 1,
  265. limit: 20,
  266. }
  267. getList()
  268. }
  269. const getStatusLabel = (value: any) => {
  270. const temp = statusList.filter((i: any) => i.value === value)
  271. return temp.length ? temp[0].label : '-'
  272. }
  273. const reset = () => {
  274. form.value = {
  275. name: '',
  276. category: [],
  277. status: 0,
  278. }
  279. pageForm.value = {
  280. page: 1,
  281. limit: 20,
  282. }
  283. total.value = 0
  284. getList()
  285. }
  286. const edit = (row: any) => {
  287. dataForEdit.value = row
  288. componentEditVisible.value = 2
  289. }
  290. const deleteProductFunc = (row: any) => {
  291. ElMessageBox.confirm('将删除该商品, 是否继续?', '提示', {
  292. confirmButtonText: '确定',
  293. cancelButtonText: '取消',
  294. type: 'warning',
  295. }).then(() => {
  296. deleteProduct({ id: row.id }).then((res: any) => {
  297. if (res.code === 1) {
  298. getList()
  299. ElNotification({
  300. title: '删除成功',
  301. message: '正在刷新数据',
  302. duration: 3000,
  303. })
  304. }
  305. })
  306. })
  307. }
  308. const examine = (row: any) => {
  309. dataForEaxmine.value = row
  310. componentExamineVisible.value = true
  311. }
  312. const openRecord = (row: any) => {
  313. recordId.value = row.id
  314. componentRecordVisible.value = true
  315. }
  316. const getList = () => {
  317. const p: any = Object.assign({}, pageForm.value)
  318. const temp = { k: '', category: '', status: '' }
  319. if (form.value.category.length) {
  320. temp.category = form.value.category.join(',')
  321. }
  322. if (form.value.name?.length) {
  323. temp.k = form.value.name.trim()
  324. }
  325. if (statusList.map((i) => i.value).includes(form.value.status)) {
  326. temp.status = `${form.value.status}`
  327. }
  328. if (Object.keys(temp).length) {
  329. p.searchParams = JSON.stringify(temp)
  330. }
  331. loading.value = true
  332. getProductList(p)
  333. .then((res: any) => {
  334. list.value =
  335. res.result?.data?.map((main: any) => {
  336. const t = main.images.split(',').filter((i: string) => i.length > 0)
  337. let status = Number(main.status)
  338. if (typeof status !== 'number') status = 0
  339. return {
  340. ...main,
  341. status,
  342. images: t.map((i: string) => {
  343. return $mediaRegExp.test(i)
  344. ? i
  345. : import.meta.env.VITE_APP_OSS_PREFIX + i
  346. }),
  347. }
  348. }) || []
  349. total.value = res.result.total
  350. })
  351. .finally(() => {
  352. loading.value = false
  353. })
  354. }
  355. const getCategoryList = () => {
  356. getCategoryTree().then((response: any) => {
  357. const res = response.result
  358. categoryList.value = res
  359. })
  360. }
  361. getList()
  362. getCategoryList()
  363. </script>
  364. <style lang="scss" scoped>
  365. .search-form {
  366. .el-input,
  367. .el-select,
  368. .el-date-editor {
  369. width: 220px;
  370. }
  371. .btn-group {
  372. margin: 0 0 22px 8px;
  373. }
  374. }
  375. </style>