InfoCard.vue 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. <script lang="ts" setup>
  2. /**
  3. * @Name: InfoCard.vue
  4. * @Description: 电脑信息卡片
  5. * @Author: xinyan
  6. */
  7. import { ref } from 'vue';
  8. import { ElCol, ElIcon } from 'element-plus';
  9. import { Picture as IconPicture, Plus, Search } from '@element-plus/icons-vue';
  10. import * as api from '/@/views/computer-information/api';
  11. import { useRouter } from 'vue-router';
  12. import { usePagination } from '/@/utils/usePagination';
  13. import { useTableData } from '/@/utils/useTableData';
  14. import EditComputerInfo from '/@/views/computer-information/components/EditComputerInfo.vue';
  15. import { useResponse } from '/@/utils/useResponse';
  16. import CreateComputer from '/@/views/computer-information/components/CreateComputer.vue';
  17. import { getShopFilterList } from '/@/views/computer-information/api';
  18. const router = useRouter();
  19. const loading = ref();
  20. const showDialog = ref(false);
  21. // const isDrawerVisible = ref(false);
  22. const searchComputer = ref('');
  23. const searchNumber = ref<string[]>([]);
  24. const searchStation = ref('');
  25. const computerInfo = ref([]);
  26. const shopOptions = ref([]);
  27. const userOptions = ref([]);
  28. const numberOptions = ref([]);
  29. const { tableOptions, handlePageChange } = usePagination(fetchCardData);
  30. tableOptions.value.limit = 12;
  31. async function fetchCardData() {
  32. const query = {
  33. page: tableOptions.value.page,
  34. limit: tableOptions.value.limit,
  35. computerNumber: searchComputer.value,
  36. shop: searchNumber.value.join(','),
  37. station: searchStation.value,
  38. };
  39. await useTableData(api.getCardData, query, tableOptions);
  40. }
  41. // 打开创建弹窗
  42. async function addComputer() {
  43. showDialog.value = true;
  44. }
  45. const checkItem = (item) => {
  46. router.push({
  47. path: '/computer/detail',
  48. query: {
  49. id: item.id,
  50. // computerNumber: item.computerNumber,
  51. },
  52. });
  53. };
  54. // async function editItem(item) {
  55. // const res = await useResponse(item.id, api.getComputerDetailOverview);
  56. // computerInfo.value = res.data;
  57. // if (computerInfo.value) {
  58. // isDrawerVisible.value = true; // 显示 Drawer
  59. // }
  60. // }
  61. // 处理图片地址
  62. const getImageUrl = (images) => {
  63. // 如果有图片,返回第一个图片的 image_url,否则返回占位图
  64. return images.length > 0 ? images[0].image_url : '';
  65. };
  66. async function fetchShopOptions() {
  67. try {
  68. const resp = await useResponse(null, api.getShopList);
  69. shopOptions.value = resp.data.map((item: any) => {
  70. return { value: item.id, label: item.platformNumber };
  71. });
  72. } catch (e) {
  73. console.log('error', e);
  74. }
  75. }
  76. async function fetchUserOptions() {
  77. try {
  78. const resp = await useResponse(null, api.getUserList);
  79. userOptions.value = resp.data.map((item: any) => {
  80. return { value: item.id, label: item.name };
  81. });
  82. } catch (e) {
  83. console.log('error', e);
  84. }
  85. }
  86. async function fetchShopFilterOptions() {
  87. try {
  88. const resp = await useResponse(null, api.getShopFilterList);
  89. numberOptions.value = resp.data.platformNumber
  90. } catch (e) {
  91. console.log('error', e);
  92. }
  93. }
  94. onMounted(() => {
  95. fetchCardData();
  96. fetchShopOptions();
  97. fetchUserOptions();
  98. fetchShopFilterOptions();
  99. });
  100. </script>
  101. <template>
  102. <!-- 标题区域 -->
  103. <el-card class="mb-5" style="border: none">
  104. <div class="flex justify-between items-baseline">
  105. <div>
  106. <span class="font-bold text-xl">电脑信息概览</span>
  107. <el-divider class="text-3xl" direction="vertical" />
  108. <el-input v-model="searchComputer" clearable placeholder="电脑编号" style="width: 200px;padding-right: 10px;" @change="fetchCardData"></el-input>
  109. <el-select
  110. v-model="searchNumber"
  111. clearable
  112. collapse-tags
  113. collapse-tags-tooltip
  114. filterable
  115. multiple
  116. placeholder="店铺编号"
  117. style="width: 200px;padding-right: 10px;"
  118. @change="fetchCardData"
  119. >
  120. <el-option v-for="item in numberOptions" :key="item" :label="item" :value="item" />
  121. </el-select>
  122. <el-input v-model="searchStation" clearable placeholder="位置" style="width: 200px" @change="fetchCardData"></el-input>
  123. </div>
  124. <span>
  125. <el-button :icon="Plus" bg text type="primary" @click="addComputer">添 加</el-button>
  126. </span>
  127. </div>
  128. </el-card>
  129. <!-- 卡片展示区域 -->
  130. <el-card class="flex-grow" style="border: none" :body-style="{ padding: '0px' }">
  131. <el-card v-loading="tableOptions.loading" class="card-container" shadow="never" style="border: none">
  132. <el-row :gutter="20">
  133. <el-col v-for="(item, index) in tableOptions.data" :key="index" :lg="4" :md="6" :sm="8" :xl="4" :xs="12" class="my-2.5">
  134. <el-card class="item-card" shadow="hover" :body-style="{ padding: '20px 20px 5px 20px' }">
  135. <div class="image-wrapper">
  136. <el-image :src="getImageUrl(item.images)" alt="电脑图片" class="card-image">
  137. <template #error>
  138. <el-icon class="card-image" style="font-size: 4rem">
  139. <icon-picture />
  140. </el-icon>
  141. </template>
  142. </el-image>
  143. </div>
  144. <hr style="box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2)" />
  145. <div class="card-content">
  146. <div class="text-wrapper">
  147. <span style="color: #808d97; font-weight: 500">电脑编号: </span>
  148. <span style="font-weight: 500">{{ item.computerNumber }}</span>
  149. </div>
  150. <div class="text-wrapper">
  151. <span style="color: #808d97; font-weight: 500">所属店铺: </span>
  152. <span style="font-weight: 500">{{ item.shopName }}</span>
  153. </div>
  154. </div>
  155. <template #footer>
  156. <div style="text-align: center; padding: 0 10px">
  157. <!--<el-button :icon="Search" bg circle text type="primary" @click="checkItem(item)" />-->
  158. <!--<el-button :icon="EditPen" bg circle text type="warning" @click="editItem(item)" />-->
  159. <el-button :icon="Search" plain round style="width: 100%" type="primary" @click="checkItem(item)"> 查看详情 </el-button>
  160. </div>
  161. </template>
  162. </el-card>
  163. </el-col>
  164. </el-row>
  165. </el-card>
  166. <div class="pagination-container" style="position: absolute; right: 30px; bottom: 30px">
  167. <el-pagination
  168. v-model:current-page="tableOptions.page"
  169. v-model:page-size="tableOptions.limit"
  170. :page-sizes="[6, 12, 24, 36, 48, 60]"
  171. :total="tableOptions.total"
  172. background
  173. layout="sizes, prev, pager, next, total, jumper"
  174. @change="handlePageChange"
  175. />
  176. </div>
  177. </el-card>
  178. <!-- 新增 Dialog -->
  179. <CreateComputer v-model="showDialog" :shopOptions :userOptions @refresh="fetchCardData"></CreateComputer>
  180. <!-- 编辑 Drawer -->
  181. <!--<EditComputerInfo-->
  182. <!-- v-if="isDrawerVisible"-->
  183. <!-- v-model="isDrawerVisible"-->
  184. <!-- :computerInfo-->
  185. <!-- :computerNumber="computerInfo.computerNumber"-->
  186. <!-- :shopOptions="shopOptions"-->
  187. <!-- :userOptions="userOptions"-->
  188. <!-- @refresh="fetchCardData"-->
  189. <!--/>-->
  190. </template>
  191. <style lang="scss" scoped>
  192. .card-container {
  193. margin-bottom: 30px;
  194. padding: 0;
  195. }
  196. .item-card {
  197. border-radius: 10px;
  198. overflow: hidden;
  199. position: relative;
  200. }
  201. .card-image {
  202. width: 100%;
  203. height: 150px;
  204. object-fit: cover;
  205. padding-bottom: 10px;
  206. }
  207. .card-content {
  208. padding-top: 10px;
  209. font-size: 14px;
  210. max-height: 60px; /* 根据需要设置最大高度 */
  211. overflow: hidden; /* 隐藏超出部分 */
  212. text-overflow: ellipsis; /* 省略号效果 */
  213. display: -webkit-box; /* 适用于多行文本处理 */
  214. -webkit-box-orient: vertical; /* 垂直排列 */
  215. }
  216. .text-wrapper {
  217. white-space: nowrap; /* 不换行 */
  218. overflow: hidden; /* 隐藏超出部分 */
  219. text-overflow: ellipsis; /* 省略号效果 */
  220. }
  221. .image-wrapper {
  222. width: 150px; /* 设置固定宽度 */
  223. height: 150px; /* 设置固定高度 */
  224. padding-bottom: 10px;
  225. margin: 0 auto; /* 横向居中 */
  226. overflow: hidden; /* 隐藏溢出部分 */
  227. }
  228. .card-footer {
  229. display: flex;
  230. justify-content: flex-end;
  231. // padding: 10px;
  232. }
  233. .pagination-container {
  234. display: flex;
  235. justify-content: flex-end;
  236. // margin-bottom: 20px;
  237. }
  238. :deep(.el-card__footer) {
  239. border-top: none;
  240. padding: 0 0 10px 0;
  241. }
  242. </style>