index.vue 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. <script setup lang="ts">
  2. import { useRole } from "./utils/hook";
  3. import { ref, computed, nextTick, onMounted } from "vue";
  4. import { PureTableBar } from "@/components/RePureTableBar";
  5. import { useRenderIcon } from "@/components/ReIcon/src/hooks";
  6. import {
  7. delay,
  8. subBefore,
  9. deviceDetection,
  10. useResizeObserver
  11. } from "@pureadmin/utils";
  12. // import Database from "~icons/ri/database-2-line";
  13. // import More from "~icons/ep/more-filled";
  14. import Delete from "~icons/ep/delete";
  15. import EditPen from "~icons/ep/edit-pen";
  16. import Refresh from "~icons/ep/refresh";
  17. import Menu from "~icons/ep/menu";
  18. import AddFill from "~icons/ri/add-circle-line";
  19. import Close from "~icons/ep/close";
  20. import Check from "~icons/ep/check";
  21. defineOptions({
  22. name: "SystemRole"
  23. });
  24. const iconClass = computed(() => {
  25. return [
  26. "w-[22px]",
  27. "h-[22px]",
  28. "flex",
  29. "justify-center",
  30. "items-center",
  31. "outline-hidden",
  32. "rounded-[4px]",
  33. "cursor-pointer",
  34. "transition-colors",
  35. "hover:bg-[#0000000f]",
  36. "dark:hover:bg-[#ffffff1f]",
  37. "dark:hover:text-[#ffffffd9]"
  38. ];
  39. });
  40. const treeRef = ref();
  41. const formRef = ref();
  42. const tableRef = ref();
  43. const contentRef = ref();
  44. const treeHeight = ref();
  45. const {
  46. form,
  47. isShow,
  48. curRow,
  49. loading,
  50. columns,
  51. rowStyle,
  52. dataList,
  53. treeData,
  54. treeProps,
  55. isLinkage,
  56. pagination,
  57. isExpandAll,
  58. isSelectAll,
  59. treeSearchValue,
  60. // buttonClass,
  61. onSearch,
  62. resetForm,
  63. openDialog,
  64. handleMenu,
  65. handleSave,
  66. handleDelete,
  67. filterMethod,
  68. transformI18n,
  69. onQueryChanged,
  70. // handleDatabase,
  71. handleSizeChange,
  72. handleCurrentChange,
  73. handleSelectionChange
  74. } = useRole(treeRef);
  75. onMounted(() => {
  76. useResizeObserver(contentRef, async () => {
  77. await nextTick();
  78. delay(60).then(() => {
  79. treeHeight.value = parseFloat(
  80. subBefore(tableRef.value.getTableDoms().tableWrapper.style.height, "px")
  81. );
  82. });
  83. });
  84. });
  85. </script>
  86. <template>
  87. <div class="main">
  88. <el-form
  89. ref="formRef"
  90. :inline="true"
  91. :model="form"
  92. class="search-form bg-bg_color w-full pl-8 pt-[12px] overflow-auto"
  93. >
  94. <el-form-item label="角色名称:" prop="name">
  95. <el-input
  96. v-model="form.name"
  97. placeholder="请输入角色名称"
  98. clearable
  99. class="w-[180px]!"
  100. />
  101. </el-form-item>
  102. <el-form-item label="角色标识:" prop="code">
  103. <el-input
  104. v-model="form.code"
  105. placeholder="请输入角色标识"
  106. clearable
  107. class="w-[180px]!"
  108. />
  109. </el-form-item>
  110. <el-form-item label="状态:" prop="status">
  111. <el-select
  112. v-model="form.status"
  113. placeholder="请选择状态"
  114. clearable
  115. class="w-[180px]!"
  116. >
  117. <el-option label="已启用" value="1" />
  118. <el-option label="已停用" value="0" />
  119. </el-select>
  120. </el-form-item>
  121. <el-form-item>
  122. <el-button
  123. type="primary"
  124. :icon="useRenderIcon('ri/search-line')"
  125. :loading="loading"
  126. @click="onSearch"
  127. >
  128. 搜索
  129. </el-button>
  130. <el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)">
  131. 重置
  132. </el-button>
  133. </el-form-item>
  134. </el-form>
  135. <div
  136. ref="contentRef"
  137. :class="['flex', deviceDetection() ? 'flex-wrap' : '']"
  138. >
  139. <PureTableBar
  140. :class="[isShow && !deviceDetection() ? 'w-[60vw]!' : 'w-full']"
  141. style="transition: width 220ms cubic-bezier(0.4, 0, 0.2, 1)"
  142. title="角色管理(仅演示,操作后不生效)"
  143. :columns="columns"
  144. @refresh="onSearch"
  145. >
  146. <template #buttons>
  147. <el-button
  148. type="primary"
  149. :icon="useRenderIcon(AddFill)"
  150. @click="openDialog()"
  151. >
  152. 新增角色
  153. </el-button>
  154. </template>
  155. <template v-slot="{ size, dynamicColumns }">
  156. <pure-table
  157. ref="tableRef"
  158. align-whole="center"
  159. showOverflowTooltip
  160. table-layout="auto"
  161. :loading="loading"
  162. :size="size"
  163. adaptive
  164. :row-style="rowStyle"
  165. :adaptiveConfig="{ offsetBottom: 108 }"
  166. :data="dataList"
  167. :columns="dynamicColumns"
  168. :pagination="{ ...pagination, size }"
  169. :header-cell-style="{
  170. background: 'var(--el-fill-color-light)',
  171. color: 'var(--el-text-color-primary)'
  172. }"
  173. @selection-change="handleSelectionChange"
  174. @page-size-change="handleSizeChange"
  175. @page-current-change="handleCurrentChange"
  176. >
  177. <template #operation="{ row }">
  178. <el-button
  179. class="reset-margin"
  180. link
  181. type="primary"
  182. :size="size"
  183. :icon="useRenderIcon(EditPen)"
  184. @click="openDialog('修改', row)"
  185. >
  186. 修改
  187. </el-button>
  188. <el-popconfirm
  189. :title="`是否确认删除角色名称为${row.name}的这条数据`"
  190. @confirm="handleDelete(row)"
  191. >
  192. <template #reference>
  193. <el-button
  194. class="reset-margin"
  195. link
  196. type="primary"
  197. :size="size"
  198. :icon="useRenderIcon(Delete)"
  199. >
  200. 删除
  201. </el-button>
  202. </template>
  203. </el-popconfirm>
  204. <el-button
  205. class="reset-margin"
  206. link
  207. type="primary"
  208. :size="size"
  209. :icon="useRenderIcon(Menu)"
  210. @click="handleMenu(row)"
  211. >
  212. 权限
  213. </el-button>
  214. <!-- <el-dropdown>
  215. <el-button
  216. class="ml-3 mt-[2px]"
  217. link
  218. type="primary"
  219. :size="size"
  220. :icon="useRenderIcon(More)"
  221. />
  222. <template #dropdown>
  223. <el-dropdown-menu>
  224. <el-dropdown-item>
  225. <el-button
  226. :class="buttonClass"
  227. link
  228. type="primary"
  229. :size="size"
  230. :icon="useRenderIcon(Menu)"
  231. @click="handleMenu"
  232. >
  233. 菜单权限
  234. </el-button>
  235. </el-dropdown-item>
  236. <el-dropdown-item>
  237. <el-button
  238. :class="buttonClass"
  239. link
  240. type="primary"
  241. :size="size"
  242. :icon="useRenderIcon(Database)"
  243. @click="handleDatabase"
  244. >
  245. 数据权限
  246. </el-button>
  247. </el-dropdown-item>
  248. </el-dropdown-menu>
  249. </template>
  250. </el-dropdown> -->
  251. </template>
  252. </pure-table>
  253. </template>
  254. </PureTableBar>
  255. <div
  256. v-if="isShow"
  257. class="min-w-[calc(100vw-60vw-268px)]! w-full mt-2 px-2 pb-2 bg-bg_color ml-2 overflow-auto"
  258. >
  259. <div class="flex justify-between w-full px-3 pt-5 pb-4">
  260. <div class="flex">
  261. <span :class="iconClass">
  262. <IconifyIconOffline
  263. v-tippy="{
  264. content: '关闭'
  265. }"
  266. class="dark:text-white"
  267. width="18px"
  268. height="18px"
  269. :icon="Close"
  270. @click="handleMenu"
  271. />
  272. </span>
  273. <span :class="[iconClass, 'ml-2']">
  274. <IconifyIconOffline
  275. v-tippy="{
  276. content: '保存菜单权限'
  277. }"
  278. class="dark:text-white"
  279. width="18px"
  280. height="18px"
  281. :icon="Check"
  282. @click="handleSave"
  283. />
  284. </span>
  285. </div>
  286. <p class="font-bold truncate">
  287. 菜单权限
  288. {{ `${curRow?.name ? `(${curRow.name})` : ""}` }}
  289. </p>
  290. </div>
  291. <el-input
  292. v-model="treeSearchValue"
  293. placeholder="请输入菜单进行搜索"
  294. class="mb-1"
  295. clearable
  296. @input="onQueryChanged"
  297. />
  298. <div class="flex flex-wrap">
  299. <el-checkbox v-model="isExpandAll" label="展开/折叠" />
  300. <el-checkbox v-model="isSelectAll" label="全选/全不选" />
  301. <el-checkbox v-model="isLinkage" label="父子联动" />
  302. </div>
  303. <el-tree-v2
  304. ref="treeRef"
  305. show-checkbox
  306. :data="treeData"
  307. :props="treeProps"
  308. :height="treeHeight"
  309. :check-strictly="!isLinkage"
  310. :filter-method="filterMethod"
  311. >
  312. <template #default="{ node }">
  313. <span>{{ transformI18n(node.label) }}</span>
  314. </template>
  315. </el-tree-v2>
  316. </div>
  317. </div>
  318. </div>
  319. </template>
  320. <style lang="scss" scoped>
  321. :deep(.el-dropdown-menu__item i) {
  322. margin: 0;
  323. }
  324. .main-content {
  325. margin: 24px 24px 0 !important;
  326. }
  327. .search-form {
  328. :deep(.el-form-item) {
  329. margin-bottom: 12px;
  330. }
  331. }
  332. </style>