index.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. <script setup lang="ts">
  2. import { reactive, ref } from 'vue'
  3. import dayjs from 'dayjs'
  4. import XEUtils from 'xe-utils'
  5. import { useI18n } from '@/hooks/web/useI18n'
  6. import { VxeFormEvents, VxeFormItemProps, VxeGrid, VxeGridInstance, VxeGridProps } from 'vxe-table'
  7. import * as PostApi from '@/api/system/post'
  8. import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
  9. import { ContentWrap } from '@/components/ContentWrap'
  10. import { PostPageReqVO, PostVO } from '@/api/system/post/types'
  11. import { rules, allSchemas } from './post.data'
  12. import { ElMessage, ElMessageBox } from 'element-plus'
  13. const { t } = useI18n() // 国际化
  14. const xGrid = ref<VxeGridInstance>()
  15. const dialogVisible = ref(false) // 是否显示弹出层
  16. const dialogTitle = ref('edit') // 弹出层标题
  17. const actionType = ref('') // 操作按钮的类型
  18. const actionLoading = ref(false) // 遮罩层
  19. const gridOptions = reactive<VxeGridProps>({
  20. loading: false,
  21. rowConfig: {
  22. keyField: 'id',
  23. isHover: true
  24. },
  25. toolbarConfig: {
  26. buttons: [{ code: 'insert_actived', name: '新增' }]
  27. },
  28. printConfig: {
  29. columns: [
  30. { field: 'name' },
  31. { field: 'code' },
  32. { field: 'sort' },
  33. { field: 'status' },
  34. { field: 'createTime' }
  35. ]
  36. },
  37. formConfig: {
  38. titleWidth: 100,
  39. titleAlign: 'right',
  40. items: [
  41. {
  42. field: 'name',
  43. title: '岗位名称',
  44. span: 8,
  45. itemRender: { name: '$input', props: { placeholder: '请输入岗位名称' } }
  46. },
  47. {
  48. field: 'code',
  49. title: '岗位编码',
  50. span: 8,
  51. itemRender: { name: '$input', props: { placeholder: '请输入岗位编码' } }
  52. },
  53. {
  54. field: 'status',
  55. title: t('common.status'),
  56. span: 8,
  57. itemRender: { name: '$select', options: getIntDictOptions(DICT_TYPE.COMMON_STATUS) }
  58. },
  59. {
  60. span: 24,
  61. align: 'center',
  62. collapseNode: true,
  63. itemRender: {
  64. name: '$buttons',
  65. children: [
  66. { props: { type: 'submit', content: t('common.query'), status: 'primary' } },
  67. { props: { type: 'reset', content: t('common.reset') } }
  68. ]
  69. }
  70. }
  71. ]
  72. },
  73. columns: [
  74. { type: 'seq', title: t('common.index'), width: 100 },
  75. { field: 'name', title: '岗位名称' },
  76. { field: 'code', title: '岗位编码' },
  77. { field: 'sort', title: '岗位顺序' },
  78. {
  79. field: 'status',
  80. title: t('common.status'),
  81. slots: {
  82. default: 'status_default'
  83. }
  84. },
  85. {
  86. field: 'createTime',
  87. title: t('common.createTime'),
  88. width: 160,
  89. sortable: true,
  90. formatter({ cellValue }) {
  91. return XEUtils.toDateString(cellValue, 'yyyy-MM-dd HH:ss:mm')
  92. }
  93. },
  94. {
  95. field: 'action',
  96. title: t('table.action'),
  97. width: '240px',
  98. showOverflow: true,
  99. slots: {
  100. default: 'action_default'
  101. }
  102. }
  103. ],
  104. pagerConfig: {
  105. border: false,
  106. background: false,
  107. perfect: true,
  108. pageSize: 10,
  109. pagerCount: 7,
  110. pageSizes: [5, 10, 15, 20, 50, 100, 200, 500],
  111. layouts: ['PrevJump', 'PrevPage', 'Jump', 'PageCount', 'NextPage', 'NextJump', 'Sizes', 'Total']
  112. },
  113. proxyConfig: {
  114. seq: true, // 启用动态序号代理(分页之后索引自动计算为当前页的起始序号)
  115. props: {
  116. result: 'list',
  117. total: 'total'
  118. },
  119. ajax: {
  120. query: ({ page, form }) => {
  121. const queryParams: PostPageReqVO = Object.assign({}, form)
  122. queryParams.pageSize = page.pageSize
  123. queryParams.pageNo = page.currentPage
  124. return new Promise(async (resolve) => {
  125. resolve(await PostApi.getPostPageApi(queryParams))
  126. })
  127. }
  128. }
  129. }
  130. })
  131. const formData = ref<PostVO>({
  132. name: '',
  133. code: '',
  134. sort: 0,
  135. status: 0,
  136. remark: '',
  137. createTime: ''
  138. })
  139. const formItems = reactive<VxeFormItemProps[]>([
  140. {
  141. field: 'id',
  142. title: 'id',
  143. visible: false
  144. },
  145. {
  146. field: 'name',
  147. title: '岗位名称',
  148. span: 8,
  149. itemRender: { name: '$input', props: { placeholder: '请输入岗位名称' } }
  150. },
  151. {
  152. field: 'code',
  153. title: '岗位编码',
  154. span: 8,
  155. itemRender: { name: '$input', props: { placeholder: '请输入岗位编码' } }
  156. },
  157. {
  158. field: 'sort',
  159. title: '岗位顺序',
  160. span: 8,
  161. itemRender: { name: '$input', props: { type: 'number', placeholder: '请输入岗位顺序' } }
  162. },
  163. {
  164. field: 'status',
  165. title: t('common.status'),
  166. span: 8,
  167. itemRender: {
  168. name: '$select',
  169. options: getIntDictOptions(DICT_TYPE.COMMON_STATUS),
  170. props: { placeholder: '请选择' }
  171. }
  172. },
  173. {
  174. align: 'center',
  175. span: 24,
  176. itemRender: {
  177. name: '$buttons',
  178. children: [
  179. { props: { type: 'submit', content: t('action.save'), status: 'primary' } },
  180. { props: { type: 'reset', content: t('common.reset') } }
  181. ]
  182. }
  183. }
  184. ])
  185. // 设置标题
  186. const setDialogTile = (type: string) => {
  187. dialogTitle.value = t('action.' + type)
  188. actionType.value = type
  189. dialogVisible.value = true
  190. }
  191. // ========== 详情相关 ==========
  192. const detailRef = ref() // 详情 Ref
  193. // 详情操作
  194. const handleDetail = (row: PostVO) => {
  195. setDialogTile('detail')
  196. detailRef.value = row
  197. }
  198. // 新增操作
  199. const handleCreate = () => {
  200. setDialogTile('create')
  201. }
  202. // 修改操作
  203. const handleUpdate = async (rowId: number) => {
  204. setDialogTile('update')
  205. // 设置数据
  206. const res = await PostApi.getPostApi(rowId)
  207. formData.value = res
  208. }
  209. // 删除操作
  210. const handleDelete = (rowId: number) => {
  211. ElMessageBox.confirm(t('common.delMessage'), t('common.confirmTitle'), {
  212. confirmButtonText: t('common.ok'),
  213. cancelButtonText: t('common.cancel'),
  214. type: 'warning'
  215. })
  216. .then(async () => {
  217. await PostApi.deletePostApi(rowId)
  218. })
  219. .finally(() => {
  220. ElMessage.success(t('common.delSuccess'))
  221. const $grid = xGrid.value
  222. $grid?.commitProxy('query')
  223. })
  224. }
  225. // 提交按钮
  226. const submitForm: VxeFormEvents.Submit = async () => {
  227. actionLoading.value = true
  228. // 提交请求
  229. try {
  230. const data = formData.value as PostVO
  231. if (actionType.value === 'create') {
  232. await PostApi.createPostApi(data)
  233. ElMessage.success(t('common.createSuccess'))
  234. } else {
  235. await PostApi.updatePostApi(data)
  236. ElMessage.success(t('common.updateSuccess'))
  237. }
  238. // 操作成功,重新加载列表
  239. dialogVisible.value = false
  240. } finally {
  241. actionLoading.value = false
  242. const $grid = xGrid.value
  243. $grid?.commitProxy('query')
  244. }
  245. }
  246. </script>
  247. <template>
  248. <ContentWrap>
  249. <vxe-grid ref="xGrid" v-bind="gridOptions">
  250. <template #toolbar_buttons>
  251. <el-button type="primary" v-hasPermi="['system:post:create']" @click="handleCreate">
  252. <Icon icon="ep:zoom-in" class="mr-5px" /> {{ t('action.add') }}
  253. </el-button>
  254. </template>
  255. <template #status_default="{ row }">
  256. <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />
  257. </template>
  258. <template #action_default="{ row }">
  259. <el-button
  260. link
  261. type="primary"
  262. v-hasPermi="['system:post:update']"
  263. @click="handleUpdate(row.id)"
  264. >
  265. <Icon icon="ep:edit" class="mr-1px" /> {{ t('action.edit') }}
  266. </el-button>
  267. <el-button
  268. link
  269. type="primary"
  270. v-hasPermi="['system:post:update']"
  271. @click="handleDetail(row)"
  272. >
  273. <Icon icon="ep:view" class="mr-1px" /> {{ t('action.detail') }}
  274. </el-button>
  275. <el-button
  276. link
  277. type="primary"
  278. v-hasPermi="['system:post:delete']"
  279. @click="handleDelete(row.id)"
  280. >
  281. <Icon icon="ep:delete" class="mr-1px" /> {{ t('action.del') }}
  282. </el-button>
  283. </template>
  284. </vxe-grid>
  285. </ContentWrap>
  286. <vxe-modal
  287. v-model="dialogVisible"
  288. id="myModal6"
  289. width="800"
  290. height="400"
  291. min-width="460"
  292. min-height="320"
  293. show-zoom
  294. resize
  295. remember
  296. storage
  297. transfer
  298. show-footer
  299. >
  300. <template #title>
  301. <span>{{ dialogTitle }}</span>
  302. </template>
  303. <template #default>
  304. <!-- 对话框(添加 / 修改) -->
  305. <vxe-form
  306. v-if="['create', 'update'].includes(actionType)"
  307. :data="formData"
  308. :items="formItems"
  309. :rules="rules"
  310. titleColon
  311. @submit="submitForm"
  312. />
  313. <Descriptions
  314. v-if="actionType === 'detail'"
  315. :schema="allSchemas.detailSchema"
  316. :data="detailRef"
  317. >
  318. <template #status="{ row }">
  319. <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />
  320. </template>
  321. <template #createTime="{ row }">
  322. <span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
  323. </template>
  324. </Descriptions>
  325. </template>
  326. </vxe-modal>
  327. </template>