index.vue 8.7 KB

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