dept.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. <template>
  2. <hc-new-card>
  3. <template #header>
  4. <div class="w-40">
  5. <el-select v-model="searchForm.tenantId" placeholder="选择所属租户" filterable clearable block>
  6. <el-option v-for="item in tenantData" :key="item.tenantId" :label="item.name" :value="item.tenantId" />
  7. </el-select>
  8. </div>
  9. <div class="ml-2 w-32">
  10. <el-select v-model="searchType" placeholder="选择搜索类型" filterable block>
  11. <el-option label="机构名称" value="deptName" />
  12. <el-option label="机构全称" value="fullName" />
  13. </el-select>
  14. </div>
  15. <div class="ml-2 w-60">
  16. <hc-search-input v-model="searchName" placeholder="请输入关键词" @search="searchClick" />
  17. </div>
  18. </template>
  19. <template #extra>
  20. <el-button hc-btn type="primary" @click="addClick">新增</el-button>
  21. <el-button hc-btn type="danger" @click="delClick">删除</el-button>
  22. </template>
  23. <hc-table
  24. ref="tableRef" :column="tableColumn" :datas="tableData" :loading="tableLoading"
  25. :is-index="false" is-new is-check :check-style="{ width: 29 }" lazy :load="tableLoad"
  26. @selection-change="tableCheckChange"
  27. >
  28. <template #tenantId="{ row }">{{ getTenantName(row) }}</template>
  29. <template #deptCategory="{ row }">{{ getDeptCategoryName(row) }}</template>
  30. <template #action="{ row }">
  31. <el-link type="warning" @click="editRowClick(row)">修改</el-link>
  32. <el-link type="success" @click="addRowClick(row)">新增子项</el-link>
  33. <el-link type="danger" @click="delRowClick(row)">删除</el-link>
  34. </template>
  35. </hc-table>
  36. <!-- 新增/修改 -->
  37. <hc-new-dialog v-model="isDialogShow" widths="620px" is-footer-center :title="iconDialogTitle" @close="dialogClose">
  38. <el-form ref="formRef" :model="formModel" :rules="formRules" label-position="top" label-width="auto">
  39. <el-row :gutter="20">
  40. <el-col :span="12">
  41. <el-form-item label="机构名称:" prop="deptName">
  42. <el-input v-model="formModel.deptName" clearable />
  43. </el-form-item>
  44. </el-col>
  45. <el-col :span="12">
  46. <el-form-item label="机构全称:" prop="fullName">
  47. <el-input v-model="formModel.fullName" clearable />
  48. </el-form-item>
  49. </el-col>
  50. <el-col :span="12">
  51. <el-form-item label="上级机构:">
  52. <el-tree-select
  53. v-model="formModel.parentId" :disabled="isChildForm" :data="levelData" :props="levelDataProps"
  54. clearable filterable check-strictly block :render-after-expand="false"
  55. />
  56. </el-form-item>
  57. </el-col>
  58. <el-col :span="12">
  59. <el-form-item label="机构类型:" prop="deptCategory">
  60. <el-select v-model="formModel.deptCategory" filterable clearable block>
  61. <el-option v-for="item in deptCategoryData" :key="item.value" :label="item.label" :value="item.value" />
  62. </el-select>
  63. </el-form-item>
  64. </el-col>
  65. <el-col :span="12">
  66. <el-form-item label="机构排序:" prop="sort">
  67. <el-input-number v-model="formModel.sort" :min="1" block controls-position="right" />
  68. </el-form-item>
  69. </el-col>
  70. <el-col :span="12">
  71. <el-form-item label="机构备注:">
  72. <el-input v-model="formModel.remark" clearable />
  73. </el-form-item>
  74. </el-col>
  75. </el-row>
  76. </el-form>
  77. <template #footer>
  78. <el-button hc-btn @click="dialogClose">取消</el-button>
  79. <el-button hc-btn type="primary" :loading="submitLoading" @click="dialogSubmit">提交</el-button>
  80. </template>
  81. </hc-new-dialog>
  82. </hc-new-card>
  83. </template>
  84. <script setup>
  85. import { nextTick, onActivated, ref } from 'vue'
  86. import mainApi from '~api/system/dept'
  87. import tenantApi from '~api/system/tenant'
  88. import { delMessage, getDictionaryData, reloadPage } from '~uti/tools'
  89. import { arrToId, formValidate, getArrValue, isNullES } from 'js-fast-way'
  90. //激活
  91. onActivated(() => {
  92. getDataApi()
  93. })
  94. const getDataApi = async () => {
  95. await getTenantData()
  96. await getDeptCategory()
  97. searchClick()
  98. }
  99. //搜索表单
  100. const searchType = ref('deptName')
  101. const searchName = ref('')
  102. const searchForm = ref({ tenantId: null })
  103. //所属租户
  104. const tenantData = ref([])
  105. const getTenantData = async () => {
  106. let newArr = []
  107. const { data } = await tenantApi.getSelect()
  108. const res = getArrValue(data)
  109. for (let i = 0; i < res.length; i++) {
  110. newArr.push({
  111. id: res[i]['id'],
  112. name: res[i]['tenantName'],
  113. tenantId: res[i]['tenantId'],
  114. })
  115. }
  116. tenantData.value = newArr
  117. }
  118. const getTenantName = ({ tenantId }) => {
  119. if (isNullES(tenantId)) return '-'
  120. const item = tenantData.value.find((item) => item.tenantId === tenantId)
  121. if (isNullES(item)) return tenantId
  122. return item.name ?? tenantId
  123. }
  124. //获取机构类型
  125. const deptCategoryData = ref([])
  126. const getDeptCategory = async () => {
  127. deptCategoryData.value = await getDictionaryData('org_category')
  128. }
  129. const getDeptCategoryName = ({ deptCategory }) => {
  130. if (isNullES(deptCategory)) return '-'
  131. const item = deptCategoryData.value.find((item) => item.value === deptCategory)
  132. if (isNullES(item)) return deptCategory
  133. return item.label ?? deptCategory
  134. }
  135. //搜索
  136. const searchClick = () => {
  137. getTableData()
  138. }
  139. //表格数据
  140. const tableRef = ref(null)
  141. const tableColumn = ref([
  142. { key: 'deptName', name: '机构名称' },
  143. { key: 'tenantId', name: '所属租户', width: 160 },
  144. { key: 'fullName', name: '机构全称' },
  145. { key: 'deptCategory', name: '机构类型', width: 100 },
  146. { key: 'sort', name: '排序', width: 80, align: 'center' },
  147. { key: 'action', name: '操作', width: 200, align: 'center' },
  148. ])
  149. //获取表格数据
  150. const tableLoading = ref(true)
  151. const tableData = ref([])
  152. const getTableData = async () => {
  153. tableData.value = []
  154. tableLoading.value = true
  155. const form = searchForm.value
  156. if (searchName.value) {
  157. form[searchType.value] = searchName.value
  158. }
  159. const { data } = await mainApi.getLazyList({
  160. ...form,
  161. parentId: 0,
  162. })
  163. tableData.value = getArrValue(data)
  164. tableLoading.value = false
  165. }
  166. //懒加载表格
  167. const tableLoad = async (row, node, resolve) => {
  168. const form = searchForm.value
  169. if (searchName.value) {
  170. form[searchType.value] = searchName.value
  171. }
  172. const { data } = await mainApi.getLazyList({
  173. ...form,
  174. parentId: row.id,
  175. })
  176. resolve(getArrValue(data))
  177. }
  178. //表格被选择
  179. const tableCheckKeys = ref([])
  180. const tableCheckChange = (rows) => {
  181. tableCheckKeys.value = rows
  182. }
  183. //上级菜单
  184. const levelDataProps = { label: 'deptName' }
  185. const levelData = ref([])
  186. const getlevelData = async () => {
  187. const { data } = await mainApi.getDeptTree()
  188. levelData.value = getArrValue(data)
  189. }
  190. //新增/修改 弹窗
  191. const isDialogShow = ref(false)
  192. const iconDialogTitle = ref('')
  193. //菜单表单
  194. const formRef = ref(null)
  195. const formModel = ref({})
  196. const formRules = {
  197. deptName: {
  198. required: true,
  199. trigger: 'blur',
  200. message: '请输入机构名称',
  201. },
  202. fullName: {
  203. required: true,
  204. trigger: 'blur',
  205. message: '请输入机构全称',
  206. },
  207. deptCategory: {
  208. required: true,
  209. trigger: 'blur',
  210. message: '请选择机构类型',
  211. },
  212. sort: {
  213. required: true,
  214. trigger: 'blur',
  215. message: '请输入菜单排序',
  216. },
  217. }
  218. //新增机构
  219. const addClick = () => {
  220. isChildForm.value = false
  221. iconDialogTitle.value = '新增机构'
  222. formModel.value = { parentId: null, deptCategory: null, sort: 1 }
  223. //显示表单弹窗
  224. nextTick(() => {
  225. isDialogShow.value = true
  226. getlevelData()
  227. })
  228. }
  229. //修改机构
  230. const editRowClick = (row) => {
  231. formModel.value = {}
  232. isChildForm.value = false
  233. iconDialogTitle.value = '修改机构'
  234. formModel.value = { ...row }
  235. //显示表单弹窗
  236. nextTick(() => {
  237. isDialogShow.value = true
  238. getlevelData()
  239. })
  240. }
  241. //新增子项
  242. const isChildForm = ref(false)
  243. const addRowClick = (row) => {
  244. isChildForm.value = true
  245. iconDialogTitle.value = '新增子机构'
  246. formModel.value = { parentId: row.id, deptCategory: null, sort: 1 }
  247. //显示表单弹窗
  248. nextTick(() => {
  249. isDialogShow.value = true
  250. getlevelData()
  251. })
  252. }
  253. //提交表单
  254. const submitLoading = ref(false)
  255. const dialogSubmit = async () => {
  256. const formRes = await formValidate(formRef.value)
  257. if (!formRes) return false
  258. submitLoading.value = true
  259. //处理数据
  260. const form = formModel.value
  261. form.parentId = form.parentId ?? '0'
  262. form.tenantId = form.tenantId ?? ''
  263. //发起请求
  264. const { error, code, msg } = await mainApi.submit(form)
  265. submitLoading.value = false
  266. if (!error && code === 200) {
  267. dialogClose()
  268. window?.$message?.success('操作成功')
  269. reloadPage()
  270. } else {
  271. window?.$message?.error(msg ?? '操作失败')
  272. }
  273. }
  274. //关闭弹窗
  275. const dialogClose = () => {
  276. isDialogShow.value = false
  277. submitLoading.value = false
  278. isChildForm.value = false
  279. formModel.value = {}
  280. }
  281. //删除
  282. const delRowClick = (row) => {
  283. delMessage(async () => {
  284. const { code, msg } = await mainApi.del(row.id)
  285. if (code === 200) {
  286. window.$message.success('删除成功')
  287. reloadPage()
  288. } else {
  289. window.$message.error(msg ?? '删除失败')
  290. }
  291. })
  292. }
  293. //批量删除
  294. const delClick = () => {
  295. const rows = tableCheckKeys.value
  296. if (rows.length <= 0) {
  297. window.$message.warning('请选择要删除的数据')
  298. return false
  299. }
  300. //确认删除菜单
  301. delMessage(async () => {
  302. const ids = arrToId(rows)
  303. const { code, msg } = await mainApi.del(ids)
  304. if (code === 200) {
  305. window.$message.success('删除成功')
  306. reloadPage()
  307. } else {
  308. window.$message.error(msg ?? '删除失败')
  309. }
  310. })
  311. }
  312. </script>