|
|
@@ -0,0 +1,183 @@
|
|
|
+<script setup lang="tsx">
|
|
|
+import { ref } from 'vue';
|
|
|
+import { NButton, NInput, NPopconfirm, NSwitch, NTree } from 'naive-ui';
|
|
|
+import {
|
|
|
+ fetchAddTenantPackage,
|
|
|
+ fetchDeleteTenantPackage,
|
|
|
+ fetchEditTenantPackage,
|
|
|
+ fetchGetTenantPackageList,
|
|
|
+ fetchGetTenantPackageMenus,
|
|
|
+ fetchUpdateTenantPackageMenus
|
|
|
+} from '@/service/api/tenant';
|
|
|
+import { fetchGetMenuTree } from '@/service/api';
|
|
|
+import { useTable } from '@/components/zt/Table/hooks/useTable';
|
|
|
+import { $t } from '@/locales';
|
|
|
+import { useModal } from '@/components/zt/Modal/hooks/useModal';
|
|
|
+
|
|
|
+const columns: NaiveUI.TableColumn<any>[] = [
|
|
|
+ {
|
|
|
+ type: 'selection',
|
|
|
+ align: 'center',
|
|
|
+ width: 48
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'index',
|
|
|
+ title: $t('common.index'),
|
|
|
+ align: 'center',
|
|
|
+ width: 64,
|
|
|
+ render: (_, index) => index + 1
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'packageName',
|
|
|
+ title: '套餐名称',
|
|
|
+ align: 'center',
|
|
|
+ minWidth: 200
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'status',
|
|
|
+ title: '状态',
|
|
|
+ align: 'center',
|
|
|
+ width: 120,
|
|
|
+ render: row => {
|
|
|
+ return <NSwitch value={row.status === 1} />;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ key: 'remark',
|
|
|
+ title: '备注',
|
|
|
+ align: 'center',
|
|
|
+ minWidth: 200
|
|
|
+ }
|
|
|
+];
|
|
|
+
|
|
|
+const [registerTable, { refresh, setTableLoading }] = useTable({
|
|
|
+ searchFormConfig: {
|
|
|
+ schemas: [],
|
|
|
+ inline: false,
|
|
|
+ size: 'small',
|
|
|
+ labelPlacement: 'left',
|
|
|
+ isFull: false
|
|
|
+ },
|
|
|
+ tableConfig: {
|
|
|
+ keyField: 'id',
|
|
|
+ title: '租户套餐列表',
|
|
|
+ showAddButton: true,
|
|
|
+ scrollX: 800
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+async function handleDelete(row: Recordable) {
|
|
|
+ setTableLoading(true);
|
|
|
+ await fetchDeleteTenantPackage([row.id].join(','));
|
|
|
+ refresh();
|
|
|
+}
|
|
|
+
|
|
|
+// 新增/编辑套餐 - 带菜单权限树
|
|
|
+const menuData = ref<any[]>([]);
|
|
|
+const checkedKeys = ref<number[]>([]);
|
|
|
+const currentEditId = ref<number>();
|
|
|
+const packageName = ref('');
|
|
|
+const packageRemark = ref('');
|
|
|
+
|
|
|
+const [registerModalMenu, { openModal: openMenuModal, closeModal: closeMenuModal, setSubLoading }] = useModal({
|
|
|
+ title: '新增租户套餐',
|
|
|
+ height: 600
|
|
|
+});
|
|
|
+
|
|
|
+async function handleSubmitWithMenu() {
|
|
|
+ // 提交新增/编辑套餐并分配菜单
|
|
|
+ if (!packageName.value) {
|
|
|
+ window.$message?.error('请输入套餐名称');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ setSubLoading(true);
|
|
|
+ try {
|
|
|
+ const formData: any = {
|
|
|
+ packageName: packageName.value,
|
|
|
+ remark: packageRemark.value,
|
|
|
+ status: 1
|
|
|
+ };
|
|
|
+ if (currentEditId.value) {
|
|
|
+ formData.id = currentEditId.value;
|
|
|
+ await fetchEditTenantPackage(formData);
|
|
|
+ await fetchUpdateTenantPackageMenus(currentEditId.value, checkedKeys.value);
|
|
|
+ } else {
|
|
|
+ const res = await fetchAddTenantPackage(formData);
|
|
|
+ // 如果返回了id,分配菜单
|
|
|
+ if (res?.data?.id) {
|
|
|
+ await fetchUpdateTenantPackageMenus(res.data.id, checkedKeys.value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ closeMenuModal();
|
|
|
+ refresh();
|
|
|
+ } finally {
|
|
|
+ setSubLoading(false);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function handleOpenAdd() {
|
|
|
+ currentEditId.value = undefined;
|
|
|
+ packageName.value = '';
|
|
|
+ packageRemark.value = '';
|
|
|
+ checkedKeys.value = [];
|
|
|
+ openMenuModal();
|
|
|
+ const { data } = await fetchGetMenuTree();
|
|
|
+ menuData.value = data as any[];
|
|
|
+}
|
|
|
+
|
|
|
+async function edit(row: Recordable) {
|
|
|
+ currentEditId.value = row.id;
|
|
|
+ packageName.value = row.packageName || '';
|
|
|
+ packageRemark.value = row.remark || '';
|
|
|
+ openMenuModal();
|
|
|
+ const { data: treeData } = await fetchGetMenuTree();
|
|
|
+ menuData.value = treeData as any[];
|
|
|
+ const { data: menuIds } = await fetchGetTenantPackageMenus(row.id);
|
|
|
+ checkedKeys.value = menuIds || [];
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <LayoutTable>
|
|
|
+ <ZTable :columns="columns as any" :api="fetchGetTenantPackageList" @register="registerTable" @add="handleOpenAdd">
|
|
|
+ <template #op="{ row }">
|
|
|
+ <NButton size="small" ghost type="primary" @click="edit(row)">编辑</NButton>
|
|
|
+ <NPopconfirm @positive-click="handleDelete(row)">
|
|
|
+ <template #trigger>
|
|
|
+ <NButton size="small" type="error" ghost>删除</NButton>
|
|
|
+ </template>
|
|
|
+ 确定删除吗?
|
|
|
+ </NPopconfirm>
|
|
|
+ </template>
|
|
|
+ </ZTable>
|
|
|
+ <BasicModal @register="registerModalMenu" @ok="handleSubmitWithMenu">
|
|
|
+ <div class="p-4">
|
|
|
+ <div class="mb-4">
|
|
|
+ <div class="mb-2 font-bold">
|
|
|
+ 套餐名称
|
|
|
+ <span class="text-red-500">*</span>
|
|
|
+ </div>
|
|
|
+ <NInput v-model:value="packageName" placeholder="请输入套餐名称" />
|
|
|
+ </div>
|
|
|
+ <div class="mb-4">
|
|
|
+ <div class="mb-2 font-bold">菜单权限</div>
|
|
|
+ <NTree
|
|
|
+ v-model:checked-keys="checkedKeys"
|
|
|
+ :data="menuData"
|
|
|
+ key-field="value"
|
|
|
+ checkable
|
|
|
+ cascade
|
|
|
+ default-expand-all
|
|
|
+ block-line
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div class="mb-4">
|
|
|
+ <div class="mb-2 font-bold">备注</div>
|
|
|
+ <NInput v-model:value="packageRemark" type="textarea" :rows="3" placeholder="请输入备注" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </BasicModal>
|
|
|
+ </LayoutTable>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style scoped></style>
|