OutStockProduct.vue 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. <script setup lang="ts">
  2. import {
  3. Storehouse_Stock_List,
  4. Storehouse_ProductClass_List,
  5. Storehouse_Product_Model_List,
  6. Storehouse_Product_Name_List
  7. } from '@/api/storehouse/index'
  8. import { ElMessage } from 'element-plus'
  9. import { GlobalStore } from '@/stores/index'
  10. import Drawer from '@/components/Drawer/index.vue'
  11. import { ref, reactive, onMounted, nextTick } from 'vue'
  12. import { default as vElTableInfiniteScroll } from 'el-table-infinite-scroll'
  13. type Fn = () => void
  14. let total = 0
  15. const loading = ref(false)
  16. const autoSelect = ref('')
  17. const selectTable = ref()
  18. const globalStore = GlobalStore()
  19. const classOptions = ref<any[]>([])
  20. const modelOptions = ref<any[]>([])
  21. const NameOptions = ref<any[]>([])
  22. const tableProductData = ref<any[]>([])
  23. const drawerProductRef = ref<InstanceType<typeof Drawer> | null>(null)
  24. const initParam = reactive({
  25. User_tokey: globalStore.GET_User_tokey,
  26. T_product_name: '',
  27. T_product_model: '',
  28. T_product_class: '',
  29. page: 1,
  30. page_z: 20
  31. })
  32. const callbackProductDrawer = (done: Fn) => done()
  33. const querySearchAsync = async (queryString: string) => {
  34. if (queryString) {
  35. loading.value = true
  36. globalStore.SET_isloading(true)
  37. const results = await getNameAsync(queryString)
  38. NameOptions.value = results
  39. globalStore.SET_isloading(false)
  40. loading.value = false
  41. }
  42. }
  43. const getProductModelList = async () => {
  44. globalStore.SET_isloading(true)
  45. const res: any = await Storehouse_Product_Model_List({ T_name: autoSelect.value })
  46. modelOptions.value = res.Data.map((item: any, index: number) => {
  47. return {
  48. value: item,
  49. index: index
  50. }
  51. })
  52. globalStore.SET_isloading(false)
  53. }
  54. const handleSelect = (item: any) => {
  55. initParam.T_product_name = item
  56. getProductModelList()
  57. }
  58. // 搜索模型
  59. const searchModelHandle = () => {
  60. total = 0
  61. initParam.page = 1
  62. tableProductData.value = []
  63. getProductList()
  64. }
  65. // 保存选中的数据id,row-key就是要指定一个key标识这一行的数据
  66. const getRowKey = (row: any) => {
  67. return row.Id
  68. }
  69. // 加载第二个抽屉数据
  70. const load = () => {
  71. console.log(initParam.page, total, tableProductData.value.length)
  72. if (initParam.page && total === tableProductData.value.length) {
  73. ElMessage.warning('没有更多数据了!!')
  74. return
  75. }
  76. initParam.page++
  77. getProductList()
  78. }
  79. // 勾选产品
  80. const ProductselectionChange = (selection: any[], row: any) => emit('ontableData', row)
  81. const ProductSelectionAllChange = (selection: any[]) => emit('ontableDataAll', selection)
  82. const getNameAsync = async (str: string): Promise<any> => {
  83. const res: any = await Storehouse_Product_Name_List({ T_name: str, T_class: initParam.T_product_class })
  84. if (!res.Data) return
  85. return res.Data.map((item: any, index: number) => {
  86. return {
  87. value: item,
  88. index: index
  89. }
  90. })
  91. }
  92. const getProductList = async () => {
  93. const res: any = await Storehouse_Stock_List({ ...initParam, T_name: autoSelect.value })
  94. tableProductData.value.push(...res.Data.Data)
  95. total = res.Data.Num
  96. }
  97. // 获取产品分类
  98. const getProductClassList = async () => {
  99. const res: any = await Storehouse_ProductClass_List({ page: 1, page_z: 999 })
  100. classOptions.value = res.Data.Data
  101. }
  102. onMounted(() => {
  103. getProductList()
  104. !classOptions.value.length && getProductClassList()
  105. })
  106. const productColumns = [
  107. { type: 'selection', width: 80 },
  108. { prop: 'T_product_img', label: '产品图片', name: 'T_product_img' },
  109. { prop: 'T_product_name', label: '产品名称' },
  110. { prop: 'T_product_class_name', label: '产品分类' },
  111. { prop: 'T_product_model', label: '产品型号', ellipsis: true },
  112. { prop: 'T_product_spec', label: '产品规格' },
  113. { prop: 'T_product_relation_sn', label: '关联SN', name: 'T_product_relation_sn' }
  114. ]
  115. const openDrawer = () => drawerProductRef.value?.openDrawer()
  116. const clearSelection = () => selectTable.value?.clearSelection()
  117. const selectTableChange = (row: any) => {
  118. nextTick(() => {
  119. selectTable.value?.toggleRowSelection(row, false)
  120. })
  121. }
  122. const emit = defineEmits<{ (event: 'ontableData', value: any): void; (event: 'ontableDataAll', value: any[]): void }>()
  123. defineExpose({
  124. openDrawer,
  125. clearSelection,
  126. selectTableChange
  127. })
  128. </script>
  129. <template>
  130. <Drawer ref="drawerProductRef" :handleClose="callbackProductDrawer" size="70%">
  131. <template #header="{ params }">
  132. <h4 :id="params.titleId" :class="params.titleClass">选择产品</h4>
  133. </template>
  134. <el-card class="box-card" shadow="never">
  135. <template #header>
  136. <div class="input-suffix">
  137. <el-row :gutter="20" style="margin-bottom: 0">
  138. <el-col :xl="5" :lg="8" :md="10" class="d-flex">
  139. <span class="inline-flex items-center">产品分类:</span>
  140. <el-select v-model="initParam.T_product_class" clearable placeholder="请选择分类~">
  141. <el-option v-for="item in classOptions" :key="item.Id" :label="item.T_name" :value="item.Id" />
  142. </el-select>
  143. </el-col>
  144. <el-col :xl="7" :lg="8" :md="10" class="d-flex">
  145. <span class="inline-flex items-center">产品名称:</span>
  146. <el-select
  147. v-model="autoSelect"
  148. filterable
  149. remote
  150. reserve-keyword
  151. placeholder="按产品名称搜索"
  152. remote-show-suffix
  153. :remote-method="querySearchAsync"
  154. :loading="loading"
  155. @change="handleSelect"
  156. >
  157. <el-option v-for="item in NameOptions" :key="item.value" :label="item.value" :value="item.value" />
  158. </el-select>
  159. </el-col>
  160. <el-col :xl="7" :lg="8" :md="12" class="d-flex">
  161. <span class="inline-flex items-center">产品型号:</span>
  162. <el-select v-model="initParam.T_product_model" clearable placeholder="请选择型号~">
  163. <el-option v-for="item in modelOptions" :key="item.index" :label="item.value" :value="item.value" />
  164. </el-select>
  165. <el-button type="primary" @click="searchModelHandle">搜索</el-button>
  166. </el-col>
  167. </el-row>
  168. </div>
  169. </template>
  170. <el-table
  171. ref="selectTable"
  172. :row-key="getRowKey"
  173. :data="tableProductData"
  174. style="width: 100%; height: 99%"
  175. :header-cell-style="{
  176. background: '#dedfe0',
  177. height: '50px'
  178. }"
  179. v-el-table-infinite-scroll="load"
  180. :infinite-scroll-immediate="false"
  181. infinite-scroll-distance="'50px'"
  182. @select="ProductselectionChange"
  183. @select-all="ProductSelectionAllChange"
  184. >
  185. <template v-for="item in productColumns" :key="item">
  186. <el-table-column v-if="item.type === 'index' || item.type === 'selection'" align="center" v-bind="item" />
  187. <el-table-column v-if="!item.ellipsis && item.prop" v-bind="item" align="center">
  188. <template #default="{ row }">
  189. <span v-if="item.prop === 'T_product_relation_sn'">
  190. <el-tag v-if="row.T_product_relation_sn === 1" effect="dark">是</el-tag>
  191. <el-tag v-else type="success" effect="dark">否</el-tag>
  192. </span>
  193. <el-image
  194. v-if="item.prop === 'T_product_img'"
  195. fit="cover"
  196. style="width: 50px; height: 50px"
  197. :src="row.T_product_img"
  198. :preview-src-list="[row.T_product_img]"
  199. :preview-teleported="true"
  200. >
  201. <template #error>
  202. <div class="image-slot">
  203. <el-icon><Picture /></el-icon>
  204. </div>
  205. </template>
  206. </el-image>
  207. </template>
  208. </el-table-column>
  209. <el-table-column v-if="item.ellipsis && item.prop === 'T_model'" align="center" v-bind="item">
  210. <template #default="{ row }">
  211. <el-tooltip effect="dark" :content="row.T_model" placement="bottom">
  212. {{ row.T_model }}
  213. </el-tooltip>
  214. </template>
  215. </el-table-column>
  216. <el-table-column v-if="item.ellipsis && item.prop === 'T_remark'" align="center" v-bind="item">
  217. <template #default="{ row }">
  218. <el-tooltip effect="customized" placement="left">
  219. <template #content>
  220. <div class="tooltip-content">{{ row.T_remark }}</div>
  221. </template>
  222. {{ row.T_remark }}
  223. </el-tooltip>
  224. </template>
  225. </el-table-column>
  226. </template>
  227. </el-table>
  228. </el-card>
  229. </Drawer>
  230. </template>
  231. <style scoped lang="scss">
  232. .tooltip-content {
  233. max-width: 500px;
  234. overflow-y: auto;
  235. }
  236. .box-card {
  237. height: 100%;
  238. :deep(.el-card__body) {
  239. height: calc(100% - 70px);
  240. }
  241. .sn-header {
  242. display: flex;
  243. justify-content: end;
  244. }
  245. .input-suffix {
  246. width: 100%;
  247. .inline-flex {
  248. white-space: nowrap;
  249. }
  250. .d-flex {
  251. display: flex;
  252. }
  253. }
  254. }
  255. .image-slot .el-icon {
  256. font-size: 30px;
  257. }
  258. .image-slot {
  259. display: flex;
  260. justify-content: center;
  261. align-items: center;
  262. width: 100%;
  263. height: 100%;
  264. background: var(--el-fill-color-light);
  265. color: var(--el-text-color-secondary);
  266. font-size: 30px;
  267. }
  268. </style>