123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- <template>
- <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)" />
- <CloseOutlined
- class="editable-cell-icon-check"
- :style="{ right: '-24px' }"
- @click="onCancel(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" autocomplete="off" class="w-6" />
- </a-form-item>
- <a-form-item
- name="id"
- required
- :label="treeSelectLabel"
- :hidden="type === 'edit' ? true : false"
- >
- <a-tree-select
- v-model:value="formState.id"
- :treeData="treeSelectData"
- :replace-fields="replaceFields"
- :tree-default-expand-all="true"
- :dropdown-style="{ height: '20rem' }"
- />
- </a-form-item>
- <a-form-item name="code2" label="图标编码">
- <a-input v-model:value="formState.code2" autocomplete="off" />
- </a-form-item>
- </a-form>
- </div>
- </AModal>
- </div>
- </template>
- <script lang="ts">
- import { computed, defineComponent, reactive, ref, toRaw, toRefs, unref, UnwrapRef } from 'vue'
- import { useDesign } from '/@/hooks/web/useDesign'
- import { Table, Modal, Form, Input, TreeSelect, Popconfirm, message } from 'ant-design-vue'
- import { CheckOutlined, EditOutlined, CloseOutlined } from '@ant-design/icons-vue'
- import {
- delSectionApi,
- sectionAddApi,
- sectionAllApi,
- sectionUpdateApi,
- treeResfulApi
- } from '/@/api/sys/tree'
- import { TreeResultModel } from '/@/api/model/tree'
- import { TreeRow } from '/#/tree'
- import { useMessage } from '/@/hooks/web/useMessage'
- interface FormState {
- id: string
- name: string
- code2: string
- }
- enum ModalType {
- ADD = 'add',
- EDIT = 'edit'
- }
- export default defineComponent({
- name: 'Management',
- components: {
- ATable: Table,
- AModal: Modal,
- AForm: Form,
- AInput: Input,
- ATreeSelect: TreeSelect,
- AFormItem: Form.Item,
- CheckOutlined,
- EditOutlined,
- CloseOutlined,
- 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: '',
- code2: ''
- })
- const modal = reactive({
- visible: false,
- type: ''
- })
- const formState: UnwrapRef<FormState> = reactive({
- id: '',
- name: '',
- code2: ''
- })
- // 目录操作相关
- const toggleModal = (type?: string) => {
- // 要打开form弹窗了, 设置当前的表单值
- if (!modal.visible) {
- if (row.value.id && type) {
- const unRow = unref(row)
- if (type === ModalType.ADD) {
- formState.id = unRow.depth === 3 ? unRow.parentId : unRow.id
- } else {
- formState.id = unRow.id
- formState.name = unRow.name
- formState.code2 = unRow.code2
- }
- } else {
- const { createMessage } = useMessage()
- return createMessage.warning('请先选择节点再进行操作')
- }
- }
- 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 = async () => {
- try {
- await onSubmit()
- await 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: 'code2',
- key: 'code2',
- slots: { customRender: 'code2' }
- },
- {
- 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 = async (key: string) => {
- const { id, name, code2 } = toRaw(editableData[key])
- await sectionUpdateApi({ id, name, code2 })
- // 执行保存请求 后初始化数据
- delete editableData[key]
- initData()
- }
- const onCancel = async (key: string) => {
- delete editableData[key]
- }
- const onDelete = async (key: string) => {
- try {
- await delSectionApi({ id: key })
- await initData()
- } catch (error) {}
- }
- const rules = {
- name: [{ required: true, message: '请输入名称' }],
- id: [
- { required: true, message: modal.type === ModalType.ADD ? '请选择父节点' : '请选择节点' }
- ]
- }
- const replaceFields = { children: 'children', title: 'name', value: 'id' }
- const treeSelectData = computed(() => {
- if (modal.type === ModalType.ADD) {
- return treeData.value.map(item => {
- const newItem = { ...item }
- if (item.children && item.children.length) {
- newItem.children = item.children.map(item => ({ ...item, children: [] }))
- }
- return newItem
- })
- }
- return treeData.value
- })
- const treeSelectLabel = computed(() => (modal.type === ModalType.ADD ? '父级目录' : '节点'))
- return {
- ...toRefs(modal),
- prefixCls,
- treeData,
- columns,
- toggleModal,
- formRef,
- hideModal,
- onConfirm,
- modalTitle,
- customRow,
- rowClassName,
- formState,
- rules,
- replaceFields,
- editableData,
- onEdit,
- onSave,
- onDelete,
- handleTreeOpreate,
- treeSelectData,
- treeSelectLabel,
- onCancel
- }
- }
- })
- </script>
- <style lang="less" scoped>
- @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;
- width: 50%;
- .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>
|