TableComponent.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547
  1. <template>
  2. <div class="mymediaLibrary">
  3. <!-- 表头搜索 -->
  4. <el-form :inline="true" :model="searchForm">
  5. <el-form-item class="formitem">
  6. <el-input
  7. v-model="searchForm.name"
  8. @blur="submitClick"
  9. @keydown.enter="submitClick"
  10. placeholder="请输入搜索内容"
  11. :prefix-icon="Search"
  12. ></el-input>
  13. </el-form-item>
  14. <el-form-item>
  15. <el-select
  16. style="width: 120px"
  17. v-model="searchForm.fileType"
  18. @change="submitClick"
  19. size="large"
  20. placeholder="全部"
  21. >
  22. <el-option
  23. v-for="(item, index) in [
  24. '全部',
  25. '图片',
  26. '视频',
  27. '音频',
  28. '模型',
  29. '其他',
  30. ]"
  31. :key="index"
  32. :label="item"
  33. :value="index"
  34. />
  35. </el-select>
  36. </el-form-item>
  37. <el-form-item>
  38. <el-select
  39. v-model="searchForm.dictId"
  40. style="width: 120px"
  41. @change="submitClick"
  42. size="large"
  43. placeholder="全部"
  44. >
  45. <el-option
  46. v-for="(item, index) in [...allList,...dictIdList]"
  47. :key="index"
  48. :label="item.dictName"
  49. :value="item.id"
  50. />
  51. </el-select>
  52. </el-form-item>
  53. <el-form-item style="float: right; margin-right: 0">
  54. <el-button type="primary" @click="handleAddfz">分组管理</el-button>
  55. <el-button type="primary" @click="handleAdd">上传</el-button>
  56. </el-form-item>
  57. </el-form>
  58. <!-- 表格 -->
  59. <el-table
  60. size="large"
  61. :data="tableData"
  62. style="width: 100%"
  63. :row-class-name="tableRowClassName"
  64. >
  65. <el-table-column prop="name" label="名称">
  66. <template #default="scope">
  67. <a
  68. style="color: #0960bd; cursor: pointer"
  69. v-if="scope.row.fileUrl"
  70. target="_blank"
  71. :title="scope.row.name"
  72. @click="floadileUrl(scope.row)"
  73. >
  74. {{ scope.row.name }}</a
  75. >
  76. </template>
  77. </el-table-column>
  78. <el-table-column
  79. v-for="column in columns"
  80. :key="column.prop"
  81. :prop="column.prop"
  82. align="center"
  83. :label="column.label"
  84. ></el-table-column>
  85. <el-table-column align="center" label="操作" width="150">
  86. <template #default="{ row }">
  87. <el-button link type="primary" size="small" @click="handleEdit(row)">
  88. 编辑
  89. </el-button>
  90. <span
  91. class="oper-span"
  92. @click="del(row)"
  93. style="color: var(--primaryColor)"
  94. >
  95. 删除
  96. </span>
  97. </template>
  98. </el-table-column>
  99. </el-table>
  100. <!-- 分页 -->
  101. <el-pagination
  102. class="mt-3"
  103. @size-change="handleSizeChange"
  104. @current-change="handleCurrentChange"
  105. :current-page="currentPage"
  106. :page-sizes="[10, 20, 30]"
  107. :page-size="pageSize"
  108. layout="total, sizes, prev, pager, next, jumper"
  109. :total="total"
  110. >
  111. </el-pagination>
  112. <!-- 弹窗 -->
  113. <el-dialog v-model="dialogData.show" :title="dialogData.title" width="500">
  114. <el-form :model="form" label-width="110">
  115. <el-form-item
  116. v-if="dialogData.title == '上传'"
  117. label="文件"
  118. :label-width="formLabelWidth"
  119. >
  120. <!-- <el-input v-model="addForm.name" autocomplete="off" /> -->
  121. <el-upload
  122. class="upload-demo"
  123. style="width: 100%"
  124. :multiple="false"
  125. :limit="1"
  126. :before-upload="beforeUpload"
  127. :file-list="fileList"
  128. :http-request="() => {}"
  129. :on-preview="previewFile"
  130. :accept="accept"
  131. :before-remove="removeFile"
  132. >
  133. <el-button type="primary">
  134. 上传
  135. </el-button>
  136. </el-upload>
  137. </el-form-item>
  138. <el-form-item
  139. :label="dialogData.title == '' ? '分组' : '修改分组'"
  140. :label-width="formLabelWidth"
  141. >
  142. <el-select style="width: 180px" v-model="addForm.dictId" placeholder="请选择分组">
  143. <el-option
  144. v-for="(item, index) in dictIdList"
  145. :key="index"
  146. :label="item.dictName"
  147. :value="item.id"
  148. />
  149. </el-select>
  150. </el-form-item>
  151. <div style="padding: 0 0 0 40px" v-if="dialogData.title == '上传'">
  152. <div style="margin-bottom: 10px">
  153. 支持jpg、png、jpeg、mp4、wav、mp3 、shp格式文件上传。文件大小 ≤ 2G
  154. </div>
  155. <!-- <span>注意:模型需使用zip包上传。包含贴图、模型、mtl文件,包内不得包含文件夹。</span> -->
  156. <div style="margin-bottom: 10px">
  157. <div>
  158. 上传
  159. obj:需使用zip包上传。包含贴图、模型、mtl文件,包内不得包含文件夹,文件名不得使用中文。如图:
  160. </div>
  161. <img style="width: 150px" :src="obj" alt="" />
  162. </div>
  163. <div style="margin-bottom: 10px">
  164. <div>
  165. 上传 osgb:需使用zip包上传。包含 Data 文件夹、xml
  166. 文件,包内不得包含文件夹,文件名不得使用中文。如图:
  167. </div>
  168. <img style="width: 150px" :src="osgb" alt="" />
  169. </div>
  170. </div>
  171. </el-form>
  172. <template #footer>
  173. <div class="dialog-footer">
  174. <el-button @click="dialogData.show = false">取消</el-button>
  175. <el-button type="primary" @click="handleuploadAdd">
  176. 确定
  177. </el-button>
  178. </div>
  179. </template>
  180. </el-dialog>
  181. <!-- 修改分组 -->
  182. <el-dialog v-model="dialogData.fzshow" title="分组管理" width="500">
  183. <el-form :model="form" label-width="50">
  184. <el-form-item label="分组" :label-width="formLabelWidth">
  185. <el-input v-model="dialogData.fzName" style="width: 300px;" />
  186. <el-button style="margin-left: 20px" @click="handlefzAdd" type="primary">新增</el-button>
  187. </el-form-item>
  188. <div class="itemTitle">
  189. <p>分组列表</p>
  190. <div class="itemTitleList">
  191. <div class="itemTitle-list" v-for="(item, index) in dictIdList" :key="index">
  192. <span>{{ item.dictName }}</span>
  193. <span @click="hanleFzDle(item)">删除</span>
  194. </div>
  195. </div>
  196. </div>
  197. </el-form>
  198. <template #footer>
  199. <div class="dialog-footer">
  200. <el-button @click="dialogData.fzshow = false">取消</el-button>
  201. <el-button type="primary" @click="handleuploadAdd">
  202. 确定
  203. </el-button>
  204. </div>
  205. </template>
  206. </el-dialog>
  207. </div>
  208. </template>
  209. <script setup>
  210. import { Search } from "@element-plus/icons-vue";
  211. import { ref, watch, onMounted } from "vue";
  212. import { getByKeyList, getfzdel, getdictFiledel, getaddOrUpdate } from "@/store/case";
  213. import dayjs from "dayjs";
  214. import obj from "@/assets/images/obj.jpg";
  215. import osgb from "@/assets/images/osgb.jpg";
  216. import { ElMessage, ElMessageBox } from "element-plus";
  217. // 定义 props
  218. const props = defineProps({
  219. columns: {
  220. type: Array,
  221. default: () => [],
  222. },
  223. searchColumns: {
  224. type: Array,
  225. default: () => [],
  226. },
  227. getData: {
  228. type: Function,
  229. required: true,
  230. },
  231. });
  232. // 定义响应式数据
  233. const searchForm = ref({
  234. name: "",
  235. fileType: 0,
  236. dictId: "0",
  237. });
  238. const addForm = ref({
  239. fileType: "",
  240. dictId: "",
  241. name: "",
  242. });
  243. const dialogData = ref({
  244. show: false,
  245. title: "上传",
  246. data: {},
  247. fzshow: false,
  248. fzName: '',
  249. fzList: [],
  250. });
  251. const file = ref(null);
  252. const accept = ".jpg,.png,.jpeg,.mp4,.wav,.mp3,.shp";
  253. const hanleFzDle = (item) => {
  254. ElMessageBox.confirm("确定删除?", "提示", {
  255. confirmButtonText: "确定",
  256. cancelButtonText: "取消",
  257. type: "warning",
  258. }).then(async () => {
  259. await getfzdel(item);
  260. dictIdList.value = dictIdList.value.filter(item1 => item1.id !== item.id)
  261. ElMessage({
  262. type: "success",
  263. message: "删除成功",
  264. });
  265. });
  266. console.log("upload", file);
  267. };
  268. const previewFile = (file) => {
  269. console.log("previewFile", file);
  270. };
  271. const handleEdit = (data) => {
  272. addForm.value.dictId = data.dictId;
  273. dialogData.value = {
  274. show: true,
  275. title: "修改分组",
  276. data,
  277. };
  278. };
  279. const removeFile = () => {
  280. return true;
  281. };
  282. const handleAdd = () => {
  283. addForm.value.dictId = '';
  284. dialogData.value = {
  285. show: true,
  286. title: "上传",
  287. };
  288. };
  289. const handlefzAdd = async () => {
  290. let params = {
  291. dictName: dialogData.value.fzName,
  292. };
  293. if (!params.dictName) {
  294. return ElMessage.error('请输入名称');
  295. }
  296. await getaddOrUpdate(params);
  297. ElMessage({
  298. type: "success",
  299. message: "新增成功",
  300. });
  301. getFzlist();
  302. dialogData.value.fzName = '';
  303. };
  304. const handleAddfz = () => {
  305. dialogData.value.fzshow = true;
  306. };
  307. const handleuploadAdd = () => {
  308. if (file.value) {
  309. const formData = new FormData();
  310. formData.append("file", file.value);
  311. formData.append("dictId", addForm.value.dictId);
  312. console.log(formData);
  313. }
  314. };
  315. // 定义方法
  316. const del = (row) => {
  317. console.log(file, "file");
  318. ElMessageBox.confirm("确定删除?", "提示", {
  319. confirmButtonText: "确定",
  320. cancelButtonText: "取消",
  321. type: "warning",
  322. }).then(async () => {
  323. await getdictFiledel({id: row.id});
  324. initData();
  325. ElMessage({
  326. type: "success",
  327. message: "删除成功",
  328. });
  329. });
  330. };
  331. const allList = ref([{ dictName: "全部", id: "0" }])
  332. const dictIdList = ref([]);
  333. const tableData = ref([]);
  334. const fileList = ref([]);
  335. const currentPage = ref(1);
  336. const pageSize = ref(10);
  337. const total = ref(0);
  338. onMounted(() => {
  339. document.body.classList.toggle("dark-mode");
  340. });
  341. const getFzlist = () => {
  342. getByKeyList({}).then((res) => {
  343. console.log("getByKeyList", res);
  344. dictIdList.value = res;
  345. });
  346. };
  347. getFzlist();
  348. const submitClick = () => {
  349. console.log("submitClick", searchForm.value);
  350. currentPage.value = 1;
  351. initData();
  352. };
  353. const tableRowClassName = ({ row, rowIndex }) => {
  354. if (rowIndex === 1) {
  355. return "warning-row";
  356. } else if (rowIndex === 3) {
  357. return "success-row";
  358. }
  359. return "";
  360. };
  361. // 初始化数据
  362. const initData = async () => {
  363. const { list, totalCount } = await props.getData({
  364. ...searchForm.value,
  365. fileType:
  366. searchForm.value.fileType == 0 ? "" : searchForm.value.fileType - 1,
  367. dictId: searchForm.value.dictId == 0 ? "" : searchForm.value.dictId,
  368. pageNum: currentPage.value,
  369. pageSize: pageSize.value,
  370. });
  371. tableData.value = list.map((res) => {
  372. return {
  373. ...res,
  374. statusStr:
  375. res.status == -1 ? "上传失败" : res.status == 0 ? "上传中" : "上传成功",
  376. createTime: dayjs(res.createTime).format("YYYY-MM-DD HH:mm:ss"),
  377. };
  378. });
  379. total.value = totalCount;
  380. };
  381. const floadileUrl = (record) => {
  382. if (record.fileType == 3) {
  383. let url = `/code/index.html?title=${record.fileName}&type=${record.fileFormat}&fileUrl=${record.fileUrl}#/sign-model`;
  384. return window.open(url);
  385. } else {
  386. return window.open(record.fileUrl);
  387. }
  388. };
  389. const beforeUpload = (file) => {
  390. console.log('beforeUpload', file);
  391. const filetype = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase();
  392. const isExcel = ['jpg', 'jpg', 'png', 'jpeg', 'mp4', 'wav', 'mp3', 'shp', 'zip'].includes(
  393. filetype,
  394. ); // 调用上面代码
  395. if (!isExcel) {
  396. createMessage.error('支持jpg、png、jpeg、mp4、wav、mp3 、shp、zip格式文件上传');
  397. fileList.value = [];
  398. return false;
  399. }
  400. const isLt10M = file.size / 1024 / 1024 < 2000;
  401. if (!isLt10M) {
  402. fileList.value = [];
  403. createMessage.error('上传文件不能超过 2G!');
  404. return false;
  405. }
  406. fileList.value = [file];
  407. return true;
  408. };
  409. // 监听搜索表单变化
  410. watch(searchForm, () => {
  411. currentPage.value = 1;
  412. initData();
  413. });
  414. // 处理分页大小变化
  415. const handleSizeChange = (newSize) => {
  416. pageSize.value = newSize;
  417. initData();
  418. };
  419. // 处理当前页码变化
  420. const handleCurrentChange = (newPage) => {
  421. currentPage.value = newPage;
  422. initData();
  423. };
  424. // 处理搜索按钮点击
  425. const handleSearch = () => {
  426. currentPage.value = 1;
  427. initData();
  428. };
  429. // 重置搜索表单
  430. const resetSearch = () => {
  431. Object.keys(searchForm.value).forEach((key) => {
  432. searchForm.value[key] = "";
  433. });
  434. currentPage.value = 1;
  435. initData();
  436. };
  437. // 初始化数据
  438. initData();
  439. </script>
  440. <style lang="scss">
  441. :root {
  442. // --el-bg-color: #151515;
  443. // --colorColor: #fff;
  444. }
  445. // /* 覆盖 Element Plus 的 CSS 变量 */
  446. // --el-color-primary: #1890ff;
  447. // --el-bg-color: #141414;
  448. // --el-text-color-primary: #ffffff;
  449. // /* 可以根据需要覆盖更多变量 */
  450. .mb-3 {
  451. margin-bottom: 1rem;
  452. }
  453. .mt-3 {
  454. margin-top: 1rem;
  455. }
  456. .mymediaLibrary {
  457. text-align: left;
  458. // .el-form-item{
  459. // margin-bottom: 30px;
  460. // }
  461. // .el-table th.el-table__cell{
  462. // background-color: #1d1d1d;
  463. // color: #fff;
  464. // }
  465. // width: 100%;
  466. // --el-input-bg-color: #535353;
  467. // .el-table{
  468. // background-color: #535353;
  469. // }
  470. // .el-form--inline .el-form-item{
  471. // margin-right: 10px;
  472. // }
  473. // .el-form-item, .el-select__wrapper{
  474. // background-color: #535353;
  475. // }
  476. // .el-input__wrapper, .el-select__wrapper{
  477. // background-color: #535353;
  478. // box-shadow: none;
  479. // }
  480. // .el-input__inner, .el-select__selected-item{
  481. // color: #fff;
  482. // }
  483. // /* 局部修改具有 custom-table 类名的 el-table 的背景颜色 */
  484. // .custom-table.el-table {
  485. // background-color: #535353;
  486. // }
  487. // /* 修改表头背景颜色 */
  488. // .custom-table.el-table__header-wrapper th {
  489. // background-color: #535353;
  490. // }
  491. // /* 修改表格行的背景颜色 */
  492. // .el-table tr {
  493. // background-color: #535353;
  494. // }
  495. // /* 修改表格行悬停时的背景颜色 */
  496. // .custom-table.el-table__body tr:hover>td {
  497. // background-color: #535353;
  498. // }
  499. // .el-table th.el-table__cell{
  500. // background-color: #1d1d1d
  501. // }
  502. // .el-table .el-table__cell{
  503. // border-color: #303030 !important;
  504. // }
  505. // .el-table--fit .el-table__inner-wrapper:before{
  506. // background-color: none;
  507. // }
  508. // .el-table .warning-row {
  509. // --el-table-tr-bg-color: var(--el-color-warning-light-9);
  510. // }
  511. // .el-table .success-row {
  512. // --el-table-tr-bg-color: var(--el-color-success-light-9);
  513. // }
  514. .itemTitle{
  515. width: 400px;
  516. margin: 0 8px;
  517. .itemTitleList{
  518. max-height: 240px;
  519. overflow-y: scroll;
  520. ::-webkit-scrollbar {
  521. display: none; /* Chrome Safari */
  522. }
  523. }
  524. .itemTitle-list{
  525. line-height: 30px;
  526. display: flex;
  527. justify-content: space-between;
  528. }
  529. }
  530. }
  531. </style>