|
@@ -1,22 +1,313 @@
|
|
|
<template>
|
|
|
- <div class="welcome">
|
|
|
- <!-- <House /> -->
|
|
|
+ <div :class="prefixCls" class="m-5 bg-white">
|
|
|
+ <header class="p-3">
|
|
|
+ <AButton type="primary" size="small" @click="toggleModal('add')">添加目录</AButton>
|
|
|
+ <AButton type="primary" class="ml-2" size="small" @click="toggleModal('edit')">编辑</AButton>
|
|
|
+ <AButton type="primary" class="ml-2" size="small" @click="handleTreeOpreate('upSerial')"
|
|
|
+ >上移</AButton
|
|
|
+ >
|
|
|
+ <AButton type="primary" class="ml-2" size="small" @click="handleTreeOpreate('downSerial')"
|
|
|
+ >下移</AButton
|
|
|
+ >
|
|
|
+ </header>
|
|
|
+ <section class="p-3">
|
|
|
+ <ATable
|
|
|
+ v-if="treeData.length"
|
|
|
+ :data-source="treeData"
|
|
|
+ :columns="columns"
|
|
|
+ size="small"
|
|
|
+ row-key="id"
|
|
|
+ :pagination="false"
|
|
|
+ :defaultExpandAllRows="true"
|
|
|
+ :custom-row="customRow"
|
|
|
+ :row-class-name="rowClassName"
|
|
|
+ >
|
|
|
+ <template #name="{ text, record }">
|
|
|
+ <div class="editable-cell">
|
|
|
+ <div v-if="editableData[record.id]" class="editable-cell-input-wrapper">
|
|
|
+ <a-input
|
|
|
+ v-model:value="editableData[record.id].name"
|
|
|
+ @pressEnter="onSave(record.id)"
|
|
|
+ />
|
|
|
+ <check-outlined class="editable-cell-icon-check" @click="onSave(record.id)" />
|
|
|
+ </div>
|
|
|
+ <div v-else class="editable-cell-text-wrapper">
|
|
|
+ {{ text || ' ' }}
|
|
|
+ <edit-outlined class="editable-cell-icon" @click="onEdit(record.id, record)" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #operation="{ record }">
|
|
|
+ <a-popconfirm v-if="treeData.length" title="确认删除?" @confirm="onDelete(record.id)">
|
|
|
+ <a>删除</a>
|
|
|
+ </a-popconfirm>
|
|
|
+ </template>
|
|
|
+ </ATable>
|
|
|
+ </section>
|
|
|
+ <AModal
|
|
|
+ :title="modalTitle"
|
|
|
+ :visible="visible"
|
|
|
+ @cancel="hideModal"
|
|
|
+ @ok="onConfirm"
|
|
|
+ :ok-button-props="{ size: 'small' }"
|
|
|
+ :cancel-button-props="{ size: 'small' }"
|
|
|
+ >
|
|
|
+ <div class="p-3">
|
|
|
+ <a-form :model="formState" :rules="rules" layout="vertical" ref="formRef">
|
|
|
+ <a-form-item name="name" required label="节点名称">
|
|
|
+ <a-input v-model:value="formState.name" />
|
|
|
+ </a-form-item>
|
|
|
+ <a-form-item name="id" required label="父级">
|
|
|
+ <a-tree-select
|
|
|
+ v-model:value="formState.id"
|
|
|
+ :treeData="treeData"
|
|
|
+ :replace-fields="replaceFields"
|
|
|
+ :tree-default-expand-all="true"
|
|
|
+ :dropdown-style="{ height: '20rem' }"
|
|
|
+ />
|
|
|
+ </a-form-item>
|
|
|
+ </a-form>
|
|
|
+ </div>
|
|
|
+ </AModal>
|
|
|
</div>
|
|
|
</template>
|
|
|
<script lang="ts">
|
|
|
- import { defineComponent } from 'vue'
|
|
|
- // import House from '../house/index.vue'
|
|
|
+ import { computed, defineComponent, reactive, ref, toRaw, toRefs, UnwrapRef } from 'vue'
|
|
|
+ import { useDesign } from '/@/hooks/web/useDesign'
|
|
|
+ import { Table, Modal, Form, Input, TreeSelect, Popconfirm, message } from 'ant-design-vue'
|
|
|
+ import { CheckOutlined, EditOutlined } from '@ant-design/icons-vue'
|
|
|
+ import { sectionAddApi, sectionAllApi, sectionUpdateApi, treeResfulApi } from '/@/api/sys/tree'
|
|
|
+ import { TreeResultModel } from '/@/api/model/tree'
|
|
|
+ import { TreeRow } from '/#/tree'
|
|
|
+
|
|
|
+ interface FormState {
|
|
|
+ id: string
|
|
|
+ name: string
|
|
|
+ }
|
|
|
+ enum ModalType {
|
|
|
+ ADD = 'add',
|
|
|
+ EDIT = 'edit'
|
|
|
+ }
|
|
|
export default defineComponent({
|
|
|
- name: 'Management'
|
|
|
- // components: { House }
|
|
|
+ name: 'Management',
|
|
|
+ components: {
|
|
|
+ ATable: Table,
|
|
|
+ AModal: Modal,
|
|
|
+ AForm: Form,
|
|
|
+ AInput: Input,
|
|
|
+ ATreeSelect: TreeSelect,
|
|
|
+ AFormItem: Form.Item,
|
|
|
+ CheckOutlined,
|
|
|
+ EditOutlined,
|
|
|
+ APopconfirm: Popconfirm
|
|
|
+ },
|
|
|
+ setup() {
|
|
|
+ const formRef = ref()
|
|
|
+ const { prefixCls } = useDesign('management')
|
|
|
+ const treeData = ref<TreeResultModel[]>([])
|
|
|
+ const editableData: UnwrapRef<Record<string, TreeRow>> = reactive({})
|
|
|
+
|
|
|
+ const row = ref<TreeRow>({
|
|
|
+ name: '',
|
|
|
+ code: '',
|
|
|
+ id: '',
|
|
|
+ parentId: '',
|
|
|
+ depth: 0,
|
|
|
+ serial: 0,
|
|
|
+ attribution: '',
|
|
|
+ contractId: '',
|
|
|
+ createTime: ''
|
|
|
+ })
|
|
|
+ const modal = reactive({
|
|
|
+ visible: false,
|
|
|
+ type: ''
|
|
|
+ })
|
|
|
+ const formState: UnwrapRef<FormState> = reactive({
|
|
|
+ id: '',
|
|
|
+ name: ''
|
|
|
+ })
|
|
|
+
|
|
|
+ // 目录操作相关
|
|
|
+ const toggleModal = (type?: string) => {
|
|
|
+ // 要打开form弹窗了, 设置当前的表单值
|
|
|
+ if (!modal.visible) {
|
|
|
+ }
|
|
|
+ modal.visible = !modal.visible
|
|
|
+ type && (modal.type = type)
|
|
|
+ }
|
|
|
+ const hideModal = () => (modal.visible = false)
|
|
|
+ const onSubmit = async () => {
|
|
|
+ const values = await formRef.value.validate()
|
|
|
+
|
|
|
+ const { type } = toRaw(modal)
|
|
|
+
|
|
|
+ if (type === ModalType.ADD) {
|
|
|
+ await sectionAddApi(values)
|
|
|
+ } else {
|
|
|
+ await sectionUpdateApi(values)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const onConfirm = () => {
|
|
|
+ try {
|
|
|
+ onSubmit()
|
|
|
+ initData()
|
|
|
+ toggleModal()
|
|
|
+ } catch (error) {}
|
|
|
+ }
|
|
|
+ async function initData() {
|
|
|
+ const result = await sectionAllApi()
|
|
|
+ treeData.value = result.children
|
|
|
+ }
|
|
|
+ initData()
|
|
|
+
|
|
|
+ const handleTreeOpreate = async (operation: 'upSerial' | 'downSerial') => {
|
|
|
+ const id = row.value.id
|
|
|
+ if (!id) {
|
|
|
+ return message.error('请先选中节点')
|
|
|
+ }
|
|
|
+ await treeResfulApi({ id, type: 'serial', operation })
|
|
|
+ await initData()
|
|
|
+ }
|
|
|
+
|
|
|
+ const modalTitle = computed(() => {
|
|
|
+ let title = ''
|
|
|
+ switch (modal.type) {
|
|
|
+ case ModalType.ADD:
|
|
|
+ title = '添加目录'
|
|
|
+ break
|
|
|
+ case ModalType.EDIT:
|
|
|
+ title = '编辑'
|
|
|
+ break
|
|
|
+
|
|
|
+ default:
|
|
|
+ break
|
|
|
+ }
|
|
|
+ return title
|
|
|
+ })
|
|
|
+ const columns = [
|
|
|
+ {
|
|
|
+ title: '名称',
|
|
|
+ dataIndex: 'name',
|
|
|
+ key: 'name',
|
|
|
+ slots: { customRender: 'name' }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '图表编码',
|
|
|
+ dataIndex: 'code',
|
|
|
+ key: 'code',
|
|
|
+ slots: { customRender: 'code' }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '操作',
|
|
|
+ dataIndex: 'operation',
|
|
|
+ slots: { customRender: 'operation' }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ const customRow = (record: TreeRow) => {
|
|
|
+ return {
|
|
|
+ onClick: () => {
|
|
|
+ row.value = record
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const rowClassName = (record: TreeRow) => {
|
|
|
+ return record.id === row.value.id ? 'row-active' : ''
|
|
|
+ }
|
|
|
+
|
|
|
+ const onEdit = (key: string, record: TreeRow) => {
|
|
|
+ editableData[key] = record
|
|
|
+ }
|
|
|
+
|
|
|
+ const onSave = (key: string) => {
|
|
|
+ delete editableData[key]
|
|
|
+ // 执行保存请求 后初始化数据
|
|
|
+ // initData()
|
|
|
+ }
|
|
|
+
|
|
|
+ const onDelete = (key: string) => {
|
|
|
+ // 执行删除请求 后初始化数据
|
|
|
+ // initData()
|
|
|
+ }
|
|
|
+
|
|
|
+ const rules = {
|
|
|
+ name: [{ required: true, message: '请输入名称' }],
|
|
|
+ id: [{ required: true, message: '请选择父节点' }]
|
|
|
+ }
|
|
|
+
|
|
|
+ const replaceFields = { children: 'children', title: 'name', value: 'id' }
|
|
|
+
|
|
|
+ return {
|
|
|
+ ...toRefs(modal),
|
|
|
+ prefixCls,
|
|
|
+ treeData,
|
|
|
+ columns,
|
|
|
+ toggleModal,
|
|
|
+ formRef,
|
|
|
+ hideModal,
|
|
|
+ onConfirm,
|
|
|
+ modalTitle,
|
|
|
+ customRow,
|
|
|
+ rowClassName,
|
|
|
+ formState,
|
|
|
+ rules,
|
|
|
+ replaceFields,
|
|
|
+ editableData,
|
|
|
+ onEdit,
|
|
|
+ onSave,
|
|
|
+ onDelete,
|
|
|
+ handleTreeOpreate
|
|
|
+ }
|
|
|
+ }
|
|
|
})
|
|
|
</script>
|
|
|
<style lang="less" scoped>
|
|
|
- .welcome {
|
|
|
- display: flex;
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- justify-content: center;
|
|
|
- align-items: center;
|
|
|
+ @prefix-cls: ~'@{namespace}-management';
|
|
|
+
|
|
|
+ .@{prefix-cls} {
|
|
|
+ width: calc(100% - 2.5rem);
|
|
|
+ height: calc(100% - 2.5rem);
|
|
|
+ ::v-deep(.ant-table-row.row-active) {
|
|
|
+ background: #cdefff;
|
|
|
+ }
|
|
|
+ ::v-deep(.ant-table-row > td:first-of-type) {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+ .editable-cell {
|
|
|
+ position: relative;
|
|
|
+ .editable-cell-input-wrapper,
|
|
|
+ .editable-cell-text-wrapper {
|
|
|
+ padding-right: 24px;
|
|
|
+ }
|
|
|
+ .editable-cell-text-wrapper {
|
|
|
+ padding: 5px 24px 5px 5px;
|
|
|
+ }
|
|
|
+ .editable-cell-icon,
|
|
|
+ .editable-cell-icon-check {
|
|
|
+ position: absolute;
|
|
|
+ right: 0;
|
|
|
+ width: 20px;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ .editable-cell-icon {
|
|
|
+ display: none;
|
|
|
+ margin-top: 4px;
|
|
|
+ }
|
|
|
+ .editable-cell-icon-check {
|
|
|
+ line-height: 28px;
|
|
|
+ }
|
|
|
+ .editable-cell-icon:hover,
|
|
|
+ .editable-cell-icon-check:hover {
|
|
|
+ color: #108ee9;
|
|
|
+ }
|
|
|
+ .editable-add-btn {
|
|
|
+ margin-bottom: 8px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .editable-cell:hover .editable-cell-icon {
|
|
|
+ display: inline-block;
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|