MaterialMange.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. <!--
  2. * @Author: 半生瓜 1515706227@qq.com
  3. * @Date: 2024-05-06 19:31:40
  4. * @LastEditors: 半生瓜 1515706227@qq.com
  5. * @LastEditTime: 2024-05-28 00:03:36
  6. * @FilePath: \vue-element-plus-admin-mini\src\views\zy\Menu12.vue
  7. * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
  8. -->
  9. <script setup lang="tsx">
  10. import { ElInput } from 'element-plus'
  11. import { ref } from 'vue'
  12. import { Dialog } from '@/components/Dialog'
  13. import { ContentWrap } from '@/components/ContentWrap'
  14. import { useI18n } from '@/hooks/web/useI18n'
  15. import { Table, TableColumn, TableSlotDefault } from '@/components/Table'
  16. import { upTemplate, saveTemplate } from '@/api/table'
  17. import { saveResource, getMaterial, deleteResource, batchsavecz } from '@/api/material'
  18. import { reactive, unref } from 'vue'
  19. import { ElButton, ElMessageBox, ElMessage, ElIcon } from 'element-plus'
  20. import { useTable } from '@/hooks/web/useTable'
  21. import { Search, Edit, Delete } from '@element-plus/icons-vue'
  22. import { useValidator } from '@/hooks/web/useValidator'
  23. import { Form, FormSchema } from '@/components/Form'
  24. import { useForm } from '@/hooks/web/useForm'
  25. import { BaseButton } from '@/components/Button'
  26. import { useUserStore } from '@/store/modules/user'
  27. import { log } from 'console'
  28. const PATH_URL = window.VITE_API_BASE_PATH
  29. const { required } = useValidator()
  30. const text = ref('')
  31. const userStore = useUserStore()
  32. defineOptions({
  33. name: 'TemplateManage'
  34. })
  35. const { tableRegister, tableState, tableMethods } = useTable({
  36. fetchDataApi: async () => {
  37. const { currentPage, pageSize } = tableState
  38. const res = await getMaterial({
  39. page: unref(currentPage),
  40. pageSize: unref(pageSize),
  41. name: unref(text)
  42. })
  43. res.data.content.map((item) => {
  44. item.materialIcon = PATH_URL + item.materialIcon
  45. item.icon = item.materialIcon
  46. })
  47. console.log('kankan2232', res.data.content)
  48. return {
  49. list: res.data.content,
  50. total: res.data.totalElements
  51. }
  52. }
  53. })
  54. const { loading, dataList, total, currentPage, pageSize } = tableState
  55. const { refresh, getElTableExpose } = tableMethods
  56. const { t } = useI18n()
  57. const columns = reactive<TableColumn[]>([
  58. {
  59. field: 'selection',
  60. type: 'selection'
  61. },
  62. {
  63. field: 'index',
  64. label: t('tableDemo.index'),
  65. type: 'index'
  66. },
  67. {
  68. field: 'icon',
  69. label: '图标'
  70. },
  71. {
  72. field: 'action',
  73. label: t('tableDemo.action'),
  74. slots: {
  75. default: (data) => {
  76. return (
  77. <>
  78. <ElButton type="primary" onClick={() => edittab(data)}>
  79. {t('tableDemo.edit')}
  80. </ElButton>
  81. <ElButton type="danger" onClick={() => deletetab(data)}>
  82. {t('tableDemo.delete')}
  83. </ElButton>
  84. </>
  85. )
  86. }
  87. }
  88. }
  89. ])
  90. const imageUrl = ref('')
  91. const isedit = ref('添加')
  92. //删除
  93. const deletetab = async (data: TableSlotDefault) => {
  94. ElMessageBox.confirm('确定删除该数据?')
  95. .then(async () => {
  96. let arr = {
  97. materialIds: data.row.materialId
  98. }
  99. const res = await deleteResource(arr)
  100. refresh()
  101. refresh()
  102. if (res.code == 200) {
  103. ElMessage.success('删除成功')
  104. }
  105. refresh()
  106. })
  107. .catch(() => {
  108. // catch error
  109. })
  110. }
  111. const dialogVisible = ref(false)
  112. const dialogVisible2 = ref(false)
  113. const token = userStore.getToken
  114. const Authorization = `Bearer ${token}`
  115. const headers = ref({ Authorization: Authorization })
  116. const { formRegister, formMethods } = useForm()
  117. const { getElFormExpose, getFormData } = formMethods
  118. const schema = reactive<FormSchema[]>([
  119. {
  120. field: 'materialIcon',
  121. component: 'Upload',
  122. colProps: {
  123. span: 24
  124. },
  125. label: '图标',
  126. formItemProps: {
  127. rules: [required()]
  128. },
  129. componentProps: {
  130. action: PATH_URL + '/resource/manage/uploadImg',
  131. headers: headers,
  132. showFileList: false,
  133. onSuccess: async (_response, uploadFile) => {
  134. imageUrl.value = URL.createObjectURL(uploadFile.raw!)
  135. const formData = await getFormData()
  136. formData.materialIcon = _response.data
  137. },
  138. beforeUpload: (rawFile) => {
  139. console.log('kankangeshi', rawFile)
  140. if (rawFile.type !== 'image/png' && rawFile.type !== 'image/jpeg') {
  141. ElMessage.error('上传格式:png、jpg!')
  142. return false
  143. }
  144. return true
  145. },
  146. slots: {
  147. default: () => (
  148. <>
  149. {imageUrl.value ? <img src={imageUrl.value} class="avatar" /> : null}
  150. {!imageUrl.value ? (
  151. <ElIcon class="avatar-uploader-icon" size="large" style="font-size: 50px">
  152. +
  153. </ElIcon>
  154. ) : null}
  155. </>
  156. ),
  157. tip: () => <div class="el-upload__tip">上传格式:png、jpg,大小:56x56px;</div>
  158. }
  159. }
  160. },
  161. {
  162. field: 'jsonPath',
  163. component: 'Upload',
  164. label: '材质内容',
  165. colProps: {
  166. span: 24
  167. },
  168. componentProps: {
  169. limit: 1,
  170. action: PATH_URL + '/resource/v1/addJsonFile',
  171. headers: headers,
  172. fileList: [],
  173. multiple: true,
  174. onPreview: (uploadFile) => {
  175. console.log(uploadFile)
  176. },
  177. onRemove: async (file) => {
  178. const formData = await getFormData()
  179. formData.jsonPath = ''
  180. formData.compressFileName = ''
  181. formData.uploadCompress = false
  182. },
  183. onSuccess: async (_response, uploadFile) => {
  184. console.log('kankan_response', uploadFile)
  185. const formData = await getFormData()
  186. formData.jsonPath = _response.data
  187. formData.compressFileName = uploadFile.name
  188. },
  189. beforeRemove: (uploadFile) => {},
  190. onExceed: (files, uploadFiles) => {
  191. ElMessage.warning('只能上传一个资源,请移除后重新上传')
  192. },
  193. beforeUpload: (rawFile) => {
  194. console.log('kokokoko', rawFile)
  195. // if (rawFile.type !== 'application/x-zip-compressed' && rawFile.name.indexOf('.rar') == -1) {
  196. // ElMessage.error('只能上传RAR、ZIP文件')
  197. // return false
  198. // }
  199. // return true
  200. },
  201. slots: {
  202. default: () => <BaseButton type="primary">点击上传</BaseButton>,
  203. tip: () => <div class="el-upload__tip">文件类型:JSON</div>
  204. }
  205. }
  206. }
  207. ])
  208. const schema2 = reactive<FormSchema[]>([
  209. {
  210. field: 'jsonPath',
  211. component: 'Upload',
  212. label: '材质内容',
  213. colProps: {
  214. span: 24
  215. },
  216. componentProps: {
  217. limit: 1,
  218. action: PATH_URL + '/resource/manage/addModelCompress',
  219. headers: headers,
  220. fileList: [],
  221. multiple: true,
  222. onPreview: (uploadFile) => {
  223. console.log(uploadFile)
  224. },
  225. onRemove: async (file) => {
  226. const formData = await getFormData()
  227. formData.jsonPath = ''
  228. formData.compressFileName = ''
  229. formData.uploadCompress = false
  230. },
  231. onSuccess: async (_response, uploadFile) => {
  232. console.log('kankan_response', uploadFile)
  233. const formData = await getFormData()
  234. formData.compressFilePath = _response.data
  235. },
  236. beforeRemove: (uploadFile) => {},
  237. onExceed: (files, uploadFiles) => {
  238. ElMessage.warning('只能上传一个资源,请移除后重新上传')
  239. },
  240. beforeUpload: (rawFile) => {
  241. if (rawFile.type !== 'application/x-zip-compressed' && rawFile.name.indexOf('.rar') == -1) {
  242. ElMessage.error('只能上传RAR、ZIP文件')
  243. return false
  244. }
  245. return true
  246. },
  247. slots: {
  248. default: () => <BaseButton type="primary">点击上传</BaseButton>,
  249. tip: () => <div class="el-upload__tip">文件类型:RAR\ZIP</div>
  250. }
  251. }
  252. }
  253. ])
  254. //编辑
  255. const edittab = async (data: TableSlotDefault) => {
  256. console.log('shanchu', data)
  257. isedit.value = '编辑'
  258. dialogVisible.value = true
  259. const formRef = await getElFormExpose()
  260. const formData = await getFormData()
  261. formData.compressFileName = data.row.compressFileName
  262. formData.jsonPath = data.row.jsonPath
  263. formData.materialIcon = data.row.materialIcon.replace(PATH_URL, '')
  264. imageUrl.value = data.row.materialIcon
  265. formData.materialId = data.row.materialId
  266. schema[1].componentProps.fileList = [
  267. {
  268. name: data.row.compressFileName,
  269. url: data.row.jsonPath
  270. }
  271. ]
  272. }
  273. // 添加编辑模板管理
  274. const signIn = async () => {
  275. const formRef = await getElFormExpose()
  276. const formData = await getFormData()
  277. //如果是编辑去掉icon的拼接
  278. console.log('kakkkkak', formData)
  279. await formRef?.validate(async (isValid) => {
  280. if (isValid) {
  281. const res = await saveResource(formData)
  282. if (res) {
  283. dialogVisible.value = false
  284. refresh()
  285. }
  286. }
  287. })
  288. }
  289. // 批量添加材质
  290. const signIn2 = async () => {
  291. const formRef = await getElFormExpose()
  292. const formData = await getFormData()
  293. //如果是编辑去掉icon的拼接
  294. console.log('kakkkkak', formData)
  295. await formRef?.validate(async (isValid) => {
  296. if (isValid) {
  297. const res = await batchsavecz(formData)
  298. if (res) {
  299. dialogVisible2.value = false
  300. refresh()
  301. }
  302. }
  303. })
  304. }
  305. //多选删除
  306. const getSelections = async () => {
  307. const elTableRef = await getElTableExpose()
  308. const selections = elTableRef?.getSelectionRows()
  309. let arr = {
  310. materialIds: []
  311. }
  312. if (selections) {
  313. arr.materialIds = selections.map((item) => {
  314. return item.materialId
  315. })
  316. }
  317. if (arr.materialIds.length !== 0) {
  318. ElMessageBox.confirm('确定删除所选数据?')
  319. .then(async () => {
  320. console.log('kankan', arr)
  321. const res = await deleteResource(arr)
  322. console.log('kkkkkkss', res)
  323. if (res.code == 200) {
  324. ElMessage.success('删除成功')
  325. }
  326. refresh()
  327. })
  328. .catch(() => {
  329. // catch error
  330. })
  331. } else {
  332. ElMessage.warning('请选择数据')
  333. }
  334. }
  335. const tianjia = async () => {
  336. imageUrl.value = ''
  337. isedit.value = '添加'
  338. schema[1].componentProps.fileList = []
  339. dialogVisible.value = true
  340. }
  341. const batchtianjia = async () => {
  342. dialogVisible2.value = true
  343. }
  344. </script>
  345. <template>
  346. <ContentWrap>
  347. <div style="margin-bottom: 10px">
  348. <ElButton type="success" size="large" @click="tianjia" :icon="Edit">添加</ElButton>
  349. <ElButton type="danger" size="large" @click="getSelections" :icon="Delete">删除</ElButton>
  350. <ElButton type="success" size="large" @click="batchtianjia" :icon="Edit">批量上传</ElButton>
  351. </div>
  352. <Table
  353. v-model:pageSize="pageSize"
  354. v-model:currentPage="currentPage"
  355. :columns="columns"
  356. :image-preview="['icon']"
  357. :data="dataList"
  358. row-key="id"
  359. headerAlign="center"
  360. align="center"
  361. :loading="loading"
  362. sortable
  363. :pagination="{
  364. total: total
  365. }"
  366. @register="tableRegister"
  367. @refresh="refresh"
  368. />
  369. </ContentWrap>
  370. <Dialog v-model="dialogVisible" maxHeight="390px" width="35rem" :title="isedit">
  371. <Form :schema="schema" @register="formRegister" />
  372. <template #footer>
  373. <div style="width: 100%; display: flex; justify-content: center">
  374. <BaseButton
  375. style="font-size: 1rem; height: 2.2rem; margin: auto"
  376. type="primary"
  377. class="w-[15%]"
  378. @click="signIn"
  379. >
  380. 确定
  381. </BaseButton>
  382. </div>
  383. </template>
  384. </Dialog>
  385. <Dialog v-model="dialogVisible2" maxHeight="390px" width="35rem" :title="isedit">
  386. <Form :schema="schema2" @register="formRegister" />
  387. <template #footer>
  388. <div style="width: 100%; display: flex; justify-content: center">
  389. <BaseButton
  390. style="font-size: 1rem; height: 2.2rem; margin: auto"
  391. type="primary"
  392. class="w-[15%]"
  393. @click="signIn2"
  394. >
  395. 确定
  396. </BaseButton>
  397. </div>
  398. </template>
  399. </Dialog>
  400. </template>
  401. <style>
  402. .el-image__preview {
  403. width: 56px !important;
  404. height: 56px !important;
  405. }
  406. </style>
  407. <style lang="less">
  408. .el-upload {
  409. position: relative;
  410. overflow: hidden;
  411. cursor: pointer;
  412. border: 1px dashed var(--el-border-color);
  413. border-radius: 6px;
  414. transition: var(--el-transition-duration-fast);
  415. }
  416. .el-upload:hover {
  417. border-color: var(--el-color-primary);
  418. }
  419. .el-icon.avatar-uploader-icon {
  420. width: 120px;
  421. height: 120px;
  422. font-size: 28px;
  423. color: #8c939d;
  424. text-align: center;
  425. }
  426. .avatar {
  427. width: 120px;
  428. height: 120px;
  429. }
  430. </style>