index.vue 8.6 KB

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