index.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. <template>
  2. <div class="app-container">
  3. <el-row :gutter="20">
  4. <splitpanes :horizontal="appStore.device === 'mobile'" class="default-theme">
  5. <!--机构数据-->
  6. <pane size="16">
  7. <el-col>
  8. <div class="head-container">
  9. <el-input v-model="deptName" placeholder="请输入机构名称" clearable prefix-icon="Search" style="margin-bottom: 20px" />
  10. </div>
  11. <div class="head-container">
  12. <el-tree :data="deptOptions" :props="{ label: 'label', children: 'children' }" :expand-on-click-node="false" :filter-node-method="filterNode" ref="deptTreeRef" node-key="id" highlight-current default-expand-all @node-click="handleNodeClick" />
  13. </div>
  14. </el-col>
  15. </pane>
  16. <pane size="84">
  17. <el-col>
  18. <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
  19. <el-form-item label="名称" prop="name">
  20. <el-input
  21. v-model="queryParams.name"
  22. placeholder="请输入名称"
  23. clearable
  24. @keyup.enter="handleQuery"
  25. />
  26. </el-form-item>
  27. <el-form-item label="省份" prop="location">
  28. <el-input
  29. v-model="queryParams.location"
  30. placeholder="请输入省份"
  31. clearable
  32. @keyup.enter="handleQuery"
  33. />
  34. </el-form-item>
  35. <el-form-item label="省市区" prop="areaIds">
  36. <AddressSelect class="w-[198px]" v-model="areaIds" />
  37. </el-form-item>
  38. <el-form-item label="状态" prop="status">
  39. <el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width: 170px">
  40. <el-option
  41. v-for="dict in bool_values"
  42. :key="dict.value"
  43. :label="dict.label"
  44. :value="dict.value"
  45. />
  46. </el-select>
  47. </el-form-item>
  48. <el-form-item>
  49. <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
  50. <el-button icon="Refresh" @click="resetQuery">重置</el-button>
  51. </el-form-item>
  52. </el-form>
  53. <el-row :gutter="10" class="mb8">
  54. <el-col :span="1.5">
  55. <el-button
  56. type="primary"
  57. plain
  58. icon="Plus"
  59. @click="handleAdd"
  60. v-hasPermi="['dz:school:add']"
  61. >新增</el-button>
  62. </el-col>
  63. <el-col :span="1.5">
  64. <el-button
  65. type="success"
  66. plain
  67. icon="Edit"
  68. :disabled="single"
  69. @click="handleUpdate"
  70. v-hasPermi="['dz:school:edit']"
  71. >修改</el-button>
  72. </el-col>
  73. <el-col :span="1.5">
  74. <el-button
  75. type="danger"
  76. plain
  77. icon="Delete"
  78. :disabled="multiple"
  79. @click="handleDelete"
  80. v-hasPermi="['dz:school:remove']"
  81. >删除</el-button>
  82. </el-col>
  83. <el-col :span="1.5">
  84. <el-button
  85. type="warning"
  86. plain
  87. icon="Download"
  88. @click="handleExport"
  89. v-hasPermi="['dz:school:export']"
  90. >导出</el-button>
  91. </el-col>
  92. <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
  93. </el-row>
  94. <el-table v-loading="loading" :data="schoolList" @selection-change="handleSelectionChange">
  95. <el-table-column type="selection" width="55" align="center" />
  96. <el-table-column label="ID" align="center" prop="id" />
  97. <el-table-column label="名称" align="center" prop="name" />
  98. <!-- <el-table-column label="机构ID" align="center" prop="deptId" />-->
  99. <el-table-column label="归属机构" align="center" key="deptName" prop="dept.deptName" :show-overflow-tooltip="true" />
  100. <el-table-column label="省份" align="center" prop="location" />
  101. <el-table-column label="省" align="center" prop="pro" />
  102. <el-table-column label="市" align="center" prop="city" />
  103. <el-table-column label="区" align="center" prop="area" />
  104. <el-table-column label="状态" align="center" prop="status">
  105. <template #default="scope">
  106. <dict-tag :options="bool_values" :value="scope.row.status"/>
  107. </template>
  108. </el-table-column>
  109. <el-table-column label="备注" align="center" prop="remark" />
  110. <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  111. <template #default="scope">
  112. <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['dz:school:edit']">修改</el-button>
  113. <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['dz:school:remove']">删除</el-button>
  114. </template>
  115. </el-table-column>
  116. </el-table>
  117. <pagination
  118. v-show="total>0"
  119. :total="total"
  120. v-model:page="queryParams.pageNum"
  121. v-model:limit="queryParams.pageSize"
  122. @pagination="getList"
  123. />
  124. </el-col>
  125. </pane>
  126. </splitpanes>
  127. </el-row>
  128. <!-- 添加或修改机构校区对话框 -->
  129. <el-dialog :title="title" v-model="open" width="500px" append-to-body>
  130. <el-form ref="schoolRef" :model="form" :rules="rules" label-width="80px">
  131. <el-form-item label="名称" prop="name">
  132. <el-input v-model="form.name" placeholder="请输入名称" />
  133. </el-form-item>
  134. <!-- <el-form-item label="机构ID" prop="deptId">-->
  135. <!-- <el-input v-model="form.deptId" placeholder="请输入机构ID" />-->
  136. <!-- </el-form-item>-->
  137. <el-form-item label="归属机构" prop="deptId">
  138. <el-tree-select v-model="form.deptId" :data="enabledDeptOptions" :props="{ value: 'id', label: 'label', children: 'children' }" value-key="id" placeholder="请选择归属机构" clearable check-strictly />
  139. </el-form-item>
  140. <el-form-item label="省份" prop="location">
  141. <el-input v-model="form.location" placeholder="请输入省份" />
  142. </el-form-item>
  143. <el-form-item label="省市区" prop="areaIds" style="width: 220px;">
  144. <AddressSelect class="w-[198px]" v-model="areaIds" />
  145. </el-form-item>
  146. <!-- <el-form-item label="省" prop="pro">-->
  147. <!-- <el-input v-model="form.pro" placeholder="请输入省" />-->
  148. <!-- </el-form-item>-->
  149. <!-- <el-form-item label="市" prop="city">-->
  150. <!-- <el-input v-model="form.city" placeholder="请输入市" />-->
  151. <!-- </el-form-item>-->
  152. <!-- <el-form-item label="区" prop="area">-->
  153. <!-- <el-input v-model="form.area" placeholder="请输入区" />-->
  154. <!-- </el-form-item>-->
  155. <el-form-item label="状态" prop="status">
  156. <el-select v-model="form.status" placeholder="请选择状态">
  157. <el-option
  158. v-for="dict in bool_values"
  159. :key="dict.value"
  160. :label="dict.label"
  161. :value="parseInt(dict.value)"
  162. ></el-option>
  163. </el-select>
  164. </el-form-item>
  165. <el-form-item label="备注" prop="remark">
  166. <el-input v-model="form.remark" placeholder="请输入备注" />
  167. </el-form-item>
  168. </el-form>
  169. <template #footer>
  170. <div class="dialog-footer">
  171. <el-button type="primary" @click="submitForm">确 定</el-button>
  172. <el-button @click="cancel">取 消</el-button>
  173. </div>
  174. </template>
  175. </el-dialog>
  176. </div>
  177. </template>
  178. <script setup name="School">
  179. import { listSchool, getSchool, delSchool, addSchool, updateSchool } from "@/api/dz/school"
  180. import { deptTreeSelect } from "@/api/system/user"
  181. import useAppStore from '@/store/modules/app'
  182. import { Splitpanes, Pane } from "splitpanes"
  183. import "splitpanes/dist/splitpanes.css"
  184. import AddressSelect from '@/components/AddressSelect';
  185. const { proxy } = getCurrentInstance()
  186. const appStore = useAppStore()
  187. const { bool_values } = proxy.useDict('bool_values')
  188. const deptName = ref("")
  189. const deptOptions = ref(undefined)
  190. const enabledDeptOptions = ref(undefined)
  191. const schoolList = ref([])
  192. const open = ref(false)
  193. const loading = ref(true)
  194. const showSearch = ref(true)
  195. const ids = ref([])
  196. const single = ref(true)
  197. const multiple = ref(true)
  198. const total = ref(0)
  199. const title = ref("")
  200. const dataList = ref([]);
  201. const areaIds = ref([]);
  202. let selectedIds = [];
  203. const data = reactive({
  204. form: {},
  205. queryParams: {
  206. pageNum: 1,
  207. pageSize: 10,
  208. name: null,
  209. deptId: null,
  210. location: null,
  211. pro: null,
  212. city: null,
  213. area: null,
  214. status: null,
  215. },
  216. rules: {
  217. status: [
  218. { required: true, message: "状态(0:无效,1:有效)不能为空", trigger: "change" },
  219. { required: true, message: "机构不能为空", trigger: "change" }
  220. ],
  221. }
  222. })
  223. const { queryParams, form, rules } = toRefs(data)
  224. const queryRef = ref(null);
  225. const dateRange = ref([]);
  226. /** 查询机构校区列表 */
  227. function getList() {
  228. loading.value = true
  229. let areaObj = { pro: areaIds.value?.[0] || '', city: areaIds.value?.[1] || '', area: areaIds.value?.[2] || '' };
  230. let params = { ...proxy.addDateRange(queryParams.value), ...areaObj }
  231. // listSchool(queryParams.value).then(response => {
  232. listSchool(params).then(response => {
  233. schoolList.value = response.rows
  234. total.value = response.total
  235. loading.value = false
  236. })
  237. }
  238. /** 通过条件过滤节点 */
  239. const filterNode = (value, data) => {
  240. if (!value) return true
  241. return data.label.indexOf(value) !== -1
  242. }
  243. /** 根据名称筛选机构树 */
  244. watch(deptName, val => {
  245. proxy.$refs["deptTreeRef"].filter(val)
  246. })
  247. /** 查询机构下拉树结构 */
  248. function getDeptTree() {
  249. deptTreeSelect().then(response => {
  250. deptOptions.value = response.data
  251. enabledDeptOptions.value = filterDisabledDept(JSON.parse(JSON.stringify(response.data)))
  252. })
  253. }
  254. /** 过滤禁用的机构 */
  255. function filterDisabledDept(deptList) {
  256. return deptList.filter(dept => {
  257. if (dept.disabled) {
  258. return false
  259. }
  260. if (dept.children && dept.children.length) {
  261. dept.children = filterDisabledDept(dept.children)
  262. }
  263. return true
  264. })
  265. }
  266. /** 节点单击事件 */
  267. function handleNodeClick(data) {
  268. queryParams.value.deptId = data.id
  269. handleQuery()
  270. }
  271. /** 查询机构代理下拉树结构 */
  272. function getTreeselect() {
  273. listAgent().then(response => {
  274. agentOptions.value = []
  275. const data = { agentId: 0, name: '顶级节点', children: [] }
  276. data.children = proxy.handleTree(response.data, "agentId", "parentId")
  277. agentOptions.value.push(data)
  278. })
  279. }
  280. // 取消按钮
  281. function cancel() {
  282. open.value = false
  283. reset()
  284. }
  285. // 表单重置
  286. function reset() {
  287. form.value = {
  288. id: null,
  289. name: null,
  290. deptId: null,
  291. location: null,
  292. remark: null,
  293. pro: null,
  294. city: null,
  295. area: null,
  296. status: null,
  297. createTime: null,
  298. updateTime: null
  299. }
  300. proxy.resetForm("schoolRef")
  301. }
  302. /** 搜索按钮操作 */
  303. function handleQuery() {
  304. queryParams.value.pageNum = 1
  305. getList()
  306. }
  307. /** 重置按钮操作 */
  308. function resetQuery() {
  309. // 清空机构ID
  310. queryParams.value.deptId = undefined
  311. // 清空机构名称
  312. deptName.value = ""
  313. // 取消树节点的选中状态
  314. proxy.$refs.deptTreeRef.setCurrentKey(null)
  315. proxy.resetForm("queryRef")
  316. // 清空省市区选择
  317. areaIds.value = []
  318. handleQuery()
  319. }
  320. // 多选框选中数据
  321. function handleSelectionChange(selection) {
  322. ids.value = selection.map(item => item.id)
  323. single.value = selection.length != 1
  324. multiple.value = !selection.length
  325. }
  326. /** 新增按钮操作 */
  327. function handleAdd() {
  328. reset()
  329. open.value = true
  330. title.value = "添加机构校区"
  331. }
  332. /** 修改按钮操作 */
  333. function handleUpdate(row) {
  334. reset()
  335. const _id = row.id || ids.value
  336. getSchool(_id).then(response => {
  337. form.value = response.data
  338. open.value = true
  339. title.value = "修改机构校区"
  340. })
  341. }
  342. /** 提交按钮 */
  343. function submitForm() {
  344. proxy.$refs["schoolRef"].validate(valid => {
  345. if (valid) {
  346. // 构建省市区对象
  347. let areaObj = {
  348. pro: areaIds.value?.[0] || '',
  349. city: areaIds.value?.[1] || '',
  350. area: areaIds.value?.[2] || ''
  351. };
  352. // 合并表单数据和省市区数据
  353. const submitData = {
  354. ...form.value,
  355. ...areaObj
  356. };
  357. if (form.value.id != null) {
  358. updateSchool(form.value).then(response => {
  359. proxy.$modal.msgSuccess("修改成功")
  360. open.value = false
  361. getList()
  362. })
  363. } else {
  364. addSchool(form.value).then(response => {
  365. proxy.$modal.msgSuccess("新增成功")
  366. open.value = false
  367. getList()
  368. })
  369. }
  370. }
  371. })
  372. }
  373. /** 删除按钮操作 */
  374. function handleDelete(row) {
  375. const _ids = row.id || ids.value
  376. proxy.$modal.confirm('是否确认删除机构校区编号为"' + _ids + '"的数据项?').then(function() {
  377. return delSchool(_ids)
  378. }).then(() => {
  379. getList()
  380. proxy.$modal.msgSuccess("删除成功")
  381. }).catch(() => {})
  382. }
  383. /** 导出按钮操作 */
  384. function handleExport() {
  385. proxy.download('dz/school/export', {
  386. ...queryParams.value
  387. }, `school_${new Date().getTime()}.xlsx`)
  388. }
  389. onMounted(() => {
  390. getDeptTree()
  391. getList()
  392. })
  393. </script>