OutStockProduct.vue 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  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: 0,
  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. if (initParam.page && total === tableProductData.value.length) {
  72. ElMessage.warning('没有更多数据了!!')
  73. return
  74. }
  75. initParam.page++
  76. getProductList()
  77. }
  78. // 勾选产品
  79. const ProductselectionChange = (selection: any[], row: any) => emit('ontableData', row)
  80. const ProductSelectionAllChange = (selection: any[]) => emit('ontableDataAll', selection)
  81. const getNameAsync = async (str: string): Promise<any> => {
  82. const res: any = await Storehouse_Product_Name_List({ T_name: str, T_class: initParam.T_product_class })
  83. if (!res.Data) return
  84. return res.Data.map((item: any, index: number) => {
  85. return {
  86. value: item,
  87. index: index
  88. }
  89. })
  90. }
  91. const getProductList = async () => {
  92. const res: any = await Storehouse_Stock_List({ ...initParam, T_name: autoSelect.value })
  93. tableProductData.value.push(...res.Data.Data)
  94. total = res.Data.Num
  95. }
  96. // 获取产品分类
  97. const getProductClassList = async () => {
  98. const res: any = await Storehouse_ProductClass_List({ page: 1, page_z: 999 })
  99. classOptions.value = res.Data.Data
  100. }
  101. onMounted(() => {
  102. !classOptions.value.length && getProductClassList()
  103. })
  104. const productColumns = [
  105. { type: 'selection', width: 80 },
  106. { prop: 'T_product_img', label: '产品图片', name: 'T_product_img' },
  107. { prop: 'T_product_name', label: '产品名称' },
  108. { prop: 'T_product_class_name', label: '产品分类' },
  109. { prop: 'T_product_model', label: '产品型号', ellipsis: true },
  110. { prop: 'T_product_spec', label: '产品规格' },
  111. { prop: 'T_product_relation_sn', label: '关联SN', name: 'T_product_relation_sn' }
  112. ]
  113. const openDrawer = () => drawerProductRef.value?.openDrawer()
  114. const clearSelection = () => selectTable.value?.clearSelection()
  115. const selectTableChange = (row: any) => {
  116. nextTick(() => {
  117. selectTable.value?.toggleRowSelection(row, false)
  118. })
  119. }
  120. const emit = defineEmits<{ (event: 'ontableData', value: any): void; (event: 'ontableDataAll', value: any[]): void }>()
  121. defineExpose({
  122. openDrawer,
  123. clearSelection,
  124. selectTableChange
  125. })
  126. </script>
  127. <template>
  128. <Drawer ref="drawerProductRef" :handleClose="callbackProductDrawer" size="70%">
  129. <template #header="{ params }">
  130. <h4 :id="params.titleId" :class="params.titleClass">选择产品</h4>
  131. </template>
  132. <el-card class="box-card" shadow="never">
  133. <template #header>
  134. <div class="input-suffix">
  135. <el-row :gutter="20" style="margin-bottom: 0">
  136. <el-col :xl="5" :lg="8" :md="10" class="d-flex">
  137. <span class="inline-flex items-center">产品分类:</span>
  138. <el-select v-model="initParam.T_product_class" clearable placeholder="请选择分类~">
  139. <el-option v-for="item in classOptions" :key="item.Id" :label="item.T_name" :value="item.Id" />
  140. </el-select>
  141. </el-col>
  142. <el-col :xl="7" :lg="8" :md="10" class="d-flex">
  143. <span class="inline-flex items-center">产品名称:</span>
  144. <el-select
  145. v-model="autoSelect"
  146. filterable
  147. remote
  148. reserve-keyword
  149. placeholder="按产品名称搜索"
  150. remote-show-suffix
  151. :remote-method="querySearchAsync"
  152. :loading="loading"
  153. @change="handleSelect"
  154. >
  155. <el-option v-for="item in NameOptions" :key="item.value" :label="item.value" :value="item.value" />
  156. </el-select>
  157. </el-col>
  158. <el-col :xl="7" :lg="8" :md="12" class="d-flex">
  159. <span class="inline-flex items-center">产品型号:</span>
  160. <el-select v-model="initParam.T_product_model" clearable placeholder="请选择型号~">
  161. <el-option v-for="item in modelOptions" :key="item.index" :label="item.value" :value="item.value" />
  162. </el-select>
  163. <el-button type="primary" @click="searchModelHandle">搜索</el-button>
  164. </el-col>
  165. </el-row>
  166. </div>
  167. </template>
  168. <el-table
  169. ref="selectTable"
  170. :row-key="getRowKey"
  171. :data="tableProductData"
  172. style="width: 100%; height: 99%"
  173. :header-cell-style="{
  174. background: '#dedfe0',
  175. height: '50px'
  176. }"
  177. v-el-table-infinite-scroll="load"
  178. @select="ProductselectionChange"
  179. @select-all="ProductSelectionAllChange"
  180. >
  181. <template v-for="item in productColumns" :key="item">
  182. <el-table-column v-if="item.type === 'index' || item.type === 'selection'" align="center" v-bind="item" />
  183. <el-table-column v-if="!item.ellipsis && item.prop" v-bind="item" align="center">
  184. <template #default="{ row }">
  185. <span v-if="item.prop === 'T_product_relation_sn'">
  186. <el-tag v-if="row.T_product_relation_sn === 1" effect="dark">是</el-tag>
  187. <el-tag v-else type="success" effect="dark">否</el-tag>
  188. </span>
  189. <el-image
  190. v-if="item.prop === 'T_product_img'"
  191. fit="cover"
  192. style="width: 50px; height: 50px"
  193. :src="row.T_product_img"
  194. :preview-src-list="[row.T_product_img]"
  195. :preview-teleported="true"
  196. >
  197. <template #error>
  198. <div class="image-slot">
  199. <el-icon><Picture /></el-icon>
  200. </div>
  201. </template>
  202. </el-image>
  203. </template>
  204. </el-table-column>
  205. <el-table-column v-if="item.ellipsis && item.prop === 'T_model'" align="center" v-bind="item">
  206. <template #default="{ row }">
  207. <el-tooltip effect="dark" :content="row.T_model" placement="bottom">
  208. {{ row.T_model }}
  209. </el-tooltip>
  210. </template>
  211. </el-table-column>
  212. <el-table-column v-if="item.ellipsis && item.prop === 'T_remark'" align="center" v-bind="item">
  213. <template #default="{ row }">
  214. <el-tooltip effect="customized" placement="left">
  215. <template #content>
  216. <div class="tooltip-content">{{ row.T_remark }}</div>
  217. </template>
  218. {{ row.T_remark }}
  219. </el-tooltip>
  220. </template>
  221. </el-table-column>
  222. </template>
  223. </el-table>
  224. </el-card>
  225. </Drawer>
  226. </template>
  227. <style scoped lang="scss">
  228. .tooltip-content {
  229. max-width: 500px;
  230. overflow-y: auto;
  231. }
  232. .box-card {
  233. height: 100%;
  234. :deep(.el-card__body) {
  235. height: calc(100% - 70px);
  236. }
  237. .sn-header {
  238. display: flex;
  239. justify-content: end;
  240. }
  241. .input-suffix {
  242. width: 100%;
  243. .inline-flex {
  244. white-space: nowrap;
  245. }
  246. .d-flex {
  247. display: flex;
  248. }
  249. }
  250. }
  251. .image-slot .el-icon {
  252. font-size: 30px;
  253. }
  254. .image-slot {
  255. display: flex;
  256. justify-content: center;
  257. align-items: center;
  258. width: 100%;
  259. height: 100%;
  260. background: var(--el-fill-color-light);
  261. color: var(--el-text-color-secondary);
  262. font-size: 30px;
  263. }
  264. </style>