Initial commit
This commit is contained in:
@@ -0,0 +1,466 @@
|
||||
<!-- 用户编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
width="75%"
|
||||
:visible="visible"
|
||||
:confirm-loading="loading"
|
||||
:maxable="maxAble"
|
||||
:title="isUpdate ? '编辑服务器' : '添加服务器'"
|
||||
:body-style="{ paddingBottom: '8px' }"
|
||||
@update:visible="updateVisible"
|
||||
:maskClosable="false"
|
||||
@ok="save"
|
||||
>
|
||||
<a-tabs v-model:activeKey="activeKey" type="card">
|
||||
<a-tab-pane key="1" tab="基本信息">
|
||||
<a-form
|
||||
:label-col="{ md: { span: 8 }, sm: { span: 24 } }"
|
||||
:wrapper-col="{ md: { span: 24 }, sm: { span: 24 } }"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-form-item label="服务器名称" v-bind="validateInfos.name">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="20"
|
||||
placeholder="请输入服务器名称"
|
||||
v-model:value="form.name"
|
||||
@blur="validate('name', { trigger: 'blur' }).catch(() => {})"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="服务器IP" v-bind="validateInfos.code">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="20"
|
||||
placeholder="请输入合法的公网IP,如:0.0.0.0"
|
||||
v-model:value="form.code"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="品牌厂商" v-bind="validateInfos.brand">
|
||||
<brand-select
|
||||
v-model:value="form.brand"
|
||||
@blur="validate('brand', { trigger: 'blur' }).catch(() => {})"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="所属客户" v-bind="validateInfos.companyId">
|
||||
<SelectCompany
|
||||
:placeholder="`请选择客户`"
|
||||
v-model:value="form.customerName"
|
||||
@done="onSelect"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="备注" v-bind="validateInfos.comments">
|
||||
<!-- 编辑器 -->
|
||||
<byte-md-editor
|
||||
v-model:value="form.comments"
|
||||
:locale="zh_Hans"
|
||||
:plugins="plugins"
|
||||
height="300px"
|
||||
:editorConfig="{ lineNumbers: true }"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="账号密码">
|
||||
<a-form
|
||||
:label-col="{ md: { span: 8 }, sm: { span: 24 } }"
|
||||
:wrapper-col="{ md: { span: 24 }, sm: { span: 24 } }"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-form-item label="宝塔面板" v-bind="validateInfos.panel">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="http://ip:8888"
|
||||
v-model:value="form.panel"
|
||||
@blur="validate('panel', { trigger: 'blur' }).catch(() => {})"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="宝塔面板账号" v-bind="validateInfos.panelAccount">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="20"
|
||||
placeholder="宝塔面板账号"
|
||||
v-model:value="form.panelAccount"
|
||||
@blur="
|
||||
validate('panelAccount', { trigger: 'blur' }).catch(() => {})
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="宝塔面板密码"
|
||||
v-bind="validateInfos.panelPassword"
|
||||
>
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="20"
|
||||
placeholder="宝塔面板密码"
|
||||
v-model:value="form.panelPassword"
|
||||
@blur="
|
||||
validate('panelPassword', { trigger: 'blur' }).catch(() => {})
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="宝塔API接口秘钥" v-bind="validateInfos.btSign">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="50"
|
||||
placeholder="宝塔API接口秘钥"
|
||||
v-model:value="form.btSign"
|
||||
@blur="validate('btSign', { trigger: 'blur' }).catch(() => {})"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="服务器账号" v-bind="validateInfos.account">
|
||||
<a-input v-model:value="form.account" placeholder="root" />
|
||||
</a-form-item>
|
||||
<a-form-item label="服务器密码" v-bind="validateInfos.password">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="20"
|
||||
placeholder="服务器密码"
|
||||
v-model:value="form.password"
|
||||
@blur="validate('password', { trigger: 'blur' }).catch(() => {})"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="厂商登录账号" v-bind="validateInfos.brandAccount">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="20"
|
||||
placeholder="请输入阿里云/腾讯登录账号"
|
||||
v-model:value="form.brandAccount"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="登录密码" v-bind="validateInfos.brandPassword">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="20"
|
||||
placeholder="登录密码"
|
||||
v-model:value="form.brandPassword"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3" tab="其他配置">
|
||||
<a-form
|
||||
:label-col="{ md: { span: 8 }, sm: { span: 24 } }"
|
||||
:wrapper-col="{ md: { span: 24 }, sm: { span: 24 } }"
|
||||
layout="vertical"
|
||||
>
|
||||
<a-form-item label="服务器配置" v-bind="validateInfos.configuration">
|
||||
<configuration-select
|
||||
v-model:value="form.configuration"
|
||||
@blur="
|
||||
validate('configuration', { trigger: 'blur' }).catch(() => {})
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="购买日期">
|
||||
<a-date-picker
|
||||
class="ele-fluid"
|
||||
placeholder="请选择购买日期"
|
||||
v-model:value="startTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="结束日期">
|
||||
<a-date-picker
|
||||
class="ele-fluid"
|
||||
placeholder="请选择结束日期"
|
||||
v-model:value="endTime"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="开放端口" v-bind="validateInfos.openPort">
|
||||
<port-select
|
||||
v-model:value="form.openPort"
|
||||
@blur="validate('openPort', { trigger: 'blur' }).catch(() => {})"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态" v-bind="validateInfos.status">
|
||||
<a-select
|
||||
optionFilterProp="label"
|
||||
placeholder="请选择状态"
|
||||
:options="serverStatus"
|
||||
allow-clear
|
||||
v-model:value="form.status"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序" v-bind="validateInfos.sortNumber">
|
||||
<a-input
|
||||
allow-clear
|
||||
:maxlength="20"
|
||||
placeholder="排序"
|
||||
v-model:value="form.sortNumber"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject, ipReg } from 'ele-admin-pro';
|
||||
import type { Assets } from '@/api/oa/assets/model';
|
||||
import BrandSelect from './brand-select.vue';
|
||||
import SelectUser from '@/components/SelectUser/index.vue';
|
||||
import ConfigurationSelect from './configuration-select.vue';
|
||||
import PortSelect from './port-select.vue';
|
||||
import { addAssets, updateAssets } from '@/api/oa/assets';
|
||||
import dayjs from 'dayjs';
|
||||
import type { Dayjs } from 'dayjs';
|
||||
import { getDictionaryOptions } from '@/utils/common';
|
||||
import { UserVisibility } from '@/api/user/visibility/model';
|
||||
// 中文语言文件
|
||||
import zh_Hans from 'bytemd/locales/zh_Hans.json';
|
||||
import 'bytemd/dist/index.min.css';
|
||||
import 'github-markdown-css/github-markdown-light.css';
|
||||
// // 链接、删除线、复选框、表格等的插件
|
||||
import gfm from '@bytemd/plugin-gfm';
|
||||
// // 插件的中文语言文件
|
||||
import zh_HansGfm from '@bytemd/plugin-gfm/locales/zh_Hans.json';
|
||||
// 中文语言文件
|
||||
import 'bytemd/dist/index.min.css';
|
||||
import highlight from '@bytemd/plugin-highlight-ssr';
|
||||
import 'highlight.js/styles/default.css';
|
||||
import { Company } from "@/api/system/company/model";
|
||||
|
||||
const useForm = Form.useForm;
|
||||
// 是否是修改
|
||||
const isUpdate = ref(false);
|
||||
// 是否显示最大化切换按钮
|
||||
const maxAble = ref(true);
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: Assets | null;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void;
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
// 提交状态
|
||||
const loading = ref(false);
|
||||
const serverStatus = getDictionaryOptions('serverStatus');
|
||||
const users = ref<UserVisibility[]>([]);
|
||||
// 用户信息
|
||||
const form = reactive<Assets>({
|
||||
code: '',
|
||||
createTime: '',
|
||||
endTime: '',
|
||||
name: '',
|
||||
brand: undefined,
|
||||
account: '',
|
||||
password: '',
|
||||
configuration: '不详',
|
||||
panelAccount: '',
|
||||
panelPassword: '',
|
||||
panel: '',
|
||||
financeAmount: 0,
|
||||
financeYears: 0,
|
||||
financeRenew: 0,
|
||||
customerId: undefined,
|
||||
customerName: '',
|
||||
financeCustomerName: '',
|
||||
financeCustomerContact: '',
|
||||
financeCustomerPhone: '',
|
||||
brandAccount: '',
|
||||
brandPassword: '',
|
||||
btSign: '',
|
||||
openPort: '80',
|
||||
comments: '',
|
||||
root: 'root',
|
||||
sortNumber: 100,
|
||||
status: '0',
|
||||
type: '',
|
||||
assetsId: 0,
|
||||
visibility: 'private',
|
||||
userList: [],
|
||||
userId: undefined
|
||||
});
|
||||
|
||||
// 选项卡位置
|
||||
const activeKey = ref('1');
|
||||
// 购买日期
|
||||
const startTime = ref<Dayjs>();
|
||||
// 结束日期
|
||||
const endTime = ref<Dayjs>();
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
name: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请输入服务器名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
userId: [
|
||||
{
|
||||
required: true,
|
||||
type: 'number',
|
||||
message: '请选择客户'
|
||||
}
|
||||
],
|
||||
code: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请输入IP地址',
|
||||
trigger: 'blur'
|
||||
},
|
||||
{
|
||||
pattern: ipReg,
|
||||
message: 'IP地址不合法',
|
||||
type: 'string'
|
||||
}
|
||||
],
|
||||
brand: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请选项服务器厂商',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
configuration: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请选择服务器配置',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
openPort: [
|
||||
{
|
||||
required: true,
|
||||
type: 'any',
|
||||
message: '请选择服务器已开放端',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
panel: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写面板地址',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
panelAccount: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写面板登录账号',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
panelPassword: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请填写面板登录密码',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
status: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '服务器状态',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
visibility: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请设置可见性'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const { resetFields, validate, validateInfos } = useForm(form, rules);
|
||||
|
||||
const onSelect = (data: Company) => {
|
||||
form.customerId = data.companyId;
|
||||
form.customerName = data.companyName;
|
||||
};
|
||||
|
||||
// 插件
|
||||
const plugins = ref([
|
||||
gfm({
|
||||
locale: zh_HansGfm
|
||||
}),
|
||||
highlight()
|
||||
]);
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {
|
||||
validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
const data = {
|
||||
...form,
|
||||
startTime: startTime.value?.format('YYYY-MM-DD HH:mm:ss'),
|
||||
endTime: endTime.value?.format('YYYY-MM-DD HH:mm:ss')
|
||||
};
|
||||
// 转字符串
|
||||
data.openPort = data.openPort.toString();
|
||||
const saveOrUpdate = isUpdate.value ? updateAssets : addAssets;
|
||||
console.log(data);
|
||||
saveOrUpdate(data)
|
||||
.then((msg) => {
|
||||
loading.value = false;
|
||||
message.success(msg);
|
||||
updateVisible(false);
|
||||
emit('done');
|
||||
})
|
||||
.catch((e) => {
|
||||
loading.value = false;
|
||||
message.error(e.message);
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
if (props.data) {
|
||||
loading.value = false;
|
||||
assignObject(form, props.data);
|
||||
if (props.data.startTime) {
|
||||
startTime.value = dayjs(props.data.startTime, 'YYYY-MM-DD');
|
||||
endTime.value = dayjs(props.data.endTime, 'YYYY-MM-DD');
|
||||
} else {
|
||||
startTime.value = undefined;
|
||||
endTime.value = undefined;
|
||||
}
|
||||
if (props.data.openPort) {
|
||||
form.openPort = props.data.openPort.split(',');
|
||||
}
|
||||
isUpdate.value = true;
|
||||
} else {
|
||||
isUpdate.value = false;
|
||||
}
|
||||
} else {
|
||||
resetFields();
|
||||
startTime.value = undefined;
|
||||
endTime.value = undefined;
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<style lang="less">
|
||||
.tab-pane {
|
||||
min-height: 300px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,251 @@
|
||||
<!-- 用户编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
width="75%"
|
||||
:visible="visible"
|
||||
:confirm-loading="loading"
|
||||
:maxable="maxAble"
|
||||
:title="'服务器详情'"
|
||||
:body-style="{ paddingBottom: '36px' }"
|
||||
@update:visible="updateVisible"
|
||||
:footer="null"
|
||||
>
|
||||
<a-form
|
||||
:label-col="{ md: { span: 4 }, sm: { span: 24 } }"
|
||||
:wrapper-col="{ md: { span: 19 }, sm: { span: 24 } }"
|
||||
>
|
||||
<div class="base-form" style="margin-bottom: 20px">
|
||||
<a-descriptions :title="assets.name" bordered>
|
||||
<a-descriptions-item label="客户名称">
|
||||
{{ assets.companyName }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="服务器名称">
|
||||
{{ assets.name }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="状态">
|
||||
<a-tag v-if="assets.status === '0'" color="green">正常</a-tag>
|
||||
<a-tag v-if="assets.status === '1'" color="red">过期</a-tag>
|
||||
<a-tag v-if="assets.status === '2'" color="purple">不再续</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="服务器IP">
|
||||
{{ assets.code }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="宝塔面板">
|
||||
<a href="#" @click="openUrl(assets)">{{ assets.panel }}</a>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="宝塔账号">
|
||||
{{ assets.panelAccount }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="宝塔密码">
|
||||
<span v-role="['admin']">{{ assets.panelPassword }}</span>
|
||||
<span v-any-role="['user', 'guest', 'superAdmin', 'developer']"
|
||||
>****</span
|
||||
>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="品牌厂商">
|
||||
{{ assets.brand }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="服务器配置">
|
||||
{{ assets.configuration }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="开发端口">
|
||||
{{ assets.openPort }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="有效期">
|
||||
<div v-if="assets.startTime && assets.endTime">
|
||||
<div class="ele-text-info">{{ assets.startTime }}</div>
|
||||
<div v-html="getEndTime(assets.endTime)"></div>
|
||||
</div>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="服务器账号">
|
||||
<span class="ele-text-danger">root</span>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="服务器密码">
|
||||
<span class="ele-text-danger" v-role="['admin']">{{
|
||||
assets.password
|
||||
}}</span>
|
||||
<span v-any-role="['user', 'guest', 'superAdmin', 'developer']"
|
||||
>****</span
|
||||
>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="创建时间">
|
||||
{{ timeAgo(assets.createTime) }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="排序">
|
||||
{{ assets.sortNumber }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</div>
|
||||
<div class="base-form" style="margin-bottom: 20px">
|
||||
<a-descriptions title="服务器状态" bordered v-if="assets.systemTotal">
|
||||
<a-descriptions-item label="操作系统信息">
|
||||
{{ assets.systemTotal.system }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="面板版本">
|
||||
{{ assets.systemTotal.version }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="已不间断运行">
|
||||
{{ assets.systemTotal.time }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="CPU 核心数">
|
||||
{{ assets.systemTotal.cpuNum }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="负载状态">
|
||||
{{ assets.systemTotal.cpuRealUsed }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="物理内存容量(MB)">
|
||||
{{ assets.systemTotal.memTotal }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="已使用的物理内存(MB)">
|
||||
{{ assets.systemTotal.memRealUsed }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="可用的物理内存(MB)">
|
||||
{{ assets.systemTotal.memFree }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="缓存化的内存(MB)">
|
||||
{{ assets.systemTotal.memCached }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="系统缓冲 (MB)">
|
||||
{{ assets.systemTotal.memBuffers }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</div>
|
||||
<!-- <a-space v-if="assets.systemTotal">-->
|
||||
<!-- <div class="base-form" style="margin-bottom: 20px">-->
|
||||
<!-- <a-tabs v-model:activeKey="activeKey">-->
|
||||
<!-- <a-tab-pane key="1" tab="系统信息" force-render>-->
|
||||
<!-- <!– <byte-md-viewer :value="assets.comments" :plugins="plugins" />–>-->
|
||||
|
||||
<!-- </a-tab-pane>-->
|
||||
<!-- </a-tabs>-->
|
||||
<!-- </div>-->
|
||||
<!-- </a-space>-->
|
||||
</a-form>
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getEndTime } from '@/utils/common';
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form } from 'ant-design-vue';
|
||||
import { assignObject, timeAgo } from 'ele-admin-pro';
|
||||
import type { Assets } from '@/api/oa/assets/model';
|
||||
import { getAssets } from '@/api/oa/assets';
|
||||
|
||||
import 'bytemd/dist/index.min.css';
|
||||
import 'github-markdown-css/github-markdown-light.css';
|
||||
// // 链接、删除线、复选框、表格等的插件
|
||||
import gfm from '@bytemd/plugin-gfm';
|
||||
// // 插件的中文语言文件
|
||||
import zh_HansGfm from '@bytemd/plugin-gfm/locales/zh_Hans.json';
|
||||
// 中文语言文件
|
||||
import 'bytemd/dist/index.min.css';
|
||||
import highlight from '@bytemd/plugin-highlight-ssr';
|
||||
import 'highlight.js/styles/default.css';
|
||||
|
||||
const useForm = Form.useForm;
|
||||
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: Assets | null;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void;
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
// 插件
|
||||
const plugins = ref([
|
||||
gfm({
|
||||
locale: zh_HansGfm
|
||||
}),
|
||||
highlight()
|
||||
]);
|
||||
|
||||
// 用户信息
|
||||
const assets = reactive<Assets>({
|
||||
code: '',
|
||||
createTime: '',
|
||||
startTime: '',
|
||||
endTime: '',
|
||||
name: '',
|
||||
brand: undefined,
|
||||
account: '',
|
||||
password: '',
|
||||
configuration: '',
|
||||
panelAccount: '',
|
||||
panelPassword: '',
|
||||
panel: '',
|
||||
financeAmount: 0,
|
||||
financeYears: 0,
|
||||
financeRenew: 0,
|
||||
financeCustomerName: '',
|
||||
financeCustomerContact: '',
|
||||
financeCustomerPhone: '',
|
||||
brandAccount: '',
|
||||
brandPassword: '',
|
||||
openPort: '',
|
||||
comments: '',
|
||||
root: 'root',
|
||||
userId: 0,
|
||||
companyName: '',
|
||||
nickname: '',
|
||||
sortNumber: undefined,
|
||||
status: undefined,
|
||||
type: '',
|
||||
assetsId: 0
|
||||
});
|
||||
|
||||
// 请求状态
|
||||
const loading = ref(true);
|
||||
// 是否显示最大化切换按钮
|
||||
const maxAble = ref(true);
|
||||
// 选项卡位置
|
||||
const activeKey = ref('1');
|
||||
const { resetFields } = useForm(assets);
|
||||
const users = ref<[]>([]);
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
/* 打开外部链接 */
|
||||
const openUrl = (record) => {
|
||||
window.open(record.panel);
|
||||
};
|
||||
|
||||
const query = () => {
|
||||
const assetsId = Number(props.data?.assetsId);
|
||||
getAssets(assetsId).then((res) => {
|
||||
console.log(res);
|
||||
assets.systemTotal = JSON.parse(res.systemTotal);
|
||||
});
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
if (props.data) {
|
||||
loading.value = false;
|
||||
assignObject(assets, props.data);
|
||||
query();
|
||||
}
|
||||
} else {
|
||||
resetFields();
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<style lang="less">
|
||||
.tab-pane {
|
||||
min-height: 100px;
|
||||
}
|
||||
.important {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,65 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-form
|
||||
:label-col="{ md: { span: 6 }, sm: { span: 24 } }"
|
||||
:wrapper-col="{ md: { span: 18 }, sm: { span: 24 } }"
|
||||
>
|
||||
<a-row>
|
||||
<a-col :lg="6" :md="12" :sm="24" :xs="24">
|
||||
<a-form-item label="服务器名称">
|
||||
<a-input
|
||||
v-model:value.trim="where.name"
|
||||
placeholder="请输入服务器名称"
|
||||
allow-clear
|
||||
@pressEnter="search"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :sm="24" :xs="24">
|
||||
<a-form-item label="IP地址">
|
||||
<a-input
|
||||
v-model:value.trim="where.code"
|
||||
placeholder="请输入服务器IP"
|
||||
allow-clear
|
||||
@pressEnter="search"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :sm="24" :xs="24">
|
||||
<a-form-item class="ele-text-right" :wrapper-col="{ span: 24 }">
|
||||
<a-space>
|
||||
<a-button type="primary" @click="search">查询</a-button>
|
||||
<a-button @click="reset">重置</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import useSearch from '@/utils/use-search';
|
||||
import type { AssetsParam } from '@/api/oa/assets/model';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: AssetsParam): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where, resetFields } = useSearch<AssetsParam>({
|
||||
name: '',
|
||||
code: '',
|
||||
isExpire: ''
|
||||
});
|
||||
|
||||
/* 搜索 */
|
||||
const search = () => {
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
/* 重置 */
|
||||
const reset = () => {
|
||||
resetFields();
|
||||
search();
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,44 @@
|
||||
<!-- 选择下拉框 -->
|
||||
<template>
|
||||
<a-select
|
||||
show-search
|
||||
optionFilterProp="label"
|
||||
:options="data"
|
||||
allow-clear
|
||||
:value="value"
|
||||
:placeholder="placeholder"
|
||||
@update:value="updateValue"
|
||||
@blur="onBlur"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getDictionaryOptions } from '@/utils/common';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:value', value: string): void;
|
||||
(e: 'blur'): void;
|
||||
}>();
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
value?: string;
|
||||
placeholder?: string;
|
||||
}>(),
|
||||
{
|
||||
placeholder: '请选择服务器厂商'
|
||||
}
|
||||
);
|
||||
|
||||
// 字典数据
|
||||
const data = getDictionaryOptions('serverBrand');
|
||||
|
||||
/* 更新选中数据 */
|
||||
const updateValue = (value: string) => {
|
||||
emit('update:value', value);
|
||||
};
|
||||
/* 失去焦点 */
|
||||
const onBlur = () => {
|
||||
emit('blur');
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,45 @@
|
||||
<!-- 选择下拉框 -->
|
||||
<template>
|
||||
<a-select
|
||||
show-search
|
||||
optionFilterProp="label"
|
||||
:options="data"
|
||||
allow-clear
|
||||
:value="value"
|
||||
:placeholder="placeholder"
|
||||
@update:value="updateValue"
|
||||
@blur="onBlur"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getDictionaryOptions } from '@/utils/common';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:value', value: string): void;
|
||||
(e: 'blur'): void;
|
||||
}>();
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
value?: string;
|
||||
placeholder?: string;
|
||||
}>(),
|
||||
{
|
||||
placeholder: '请选择服务器配置'
|
||||
}
|
||||
);
|
||||
|
||||
// 字典数据
|
||||
const data = getDictionaryOptions('serverConfiguration');
|
||||
|
||||
/* 更新选中数据 */
|
||||
const updateValue = (value: string) => {
|
||||
emit('update:value', value);
|
||||
};
|
||||
|
||||
/* 失去焦点 */
|
||||
const onBlur = () => {
|
||||
emit('blur');
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,70 @@
|
||||
<!-- 选择下拉框 -->
|
||||
<template>
|
||||
<a-select
|
||||
show-search
|
||||
optionFilterProp="label"
|
||||
:options="data"
|
||||
allow-clear
|
||||
:value="value"
|
||||
:placeholder="placeholder"
|
||||
@update:value="updateValue"
|
||||
@blur="onBlur"
|
||||
@search="onSearch"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { pageCustomer } from '@/api/oa/customer';
|
||||
import type { SelectProps } from 'ant-design-vue';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:value', value: string): void;
|
||||
(e: 'blur'): void;
|
||||
}>();
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
value?: number;
|
||||
placeholder?: string;
|
||||
}>(),
|
||||
{
|
||||
placeholder: '请选择所属客户'
|
||||
}
|
||||
);
|
||||
|
||||
// 字典数据
|
||||
const data = ref<SelectProps['options']>([]);
|
||||
|
||||
/* 更新选中数据 */
|
||||
const updateValue = (value: string) => {
|
||||
emit('update:value', value);
|
||||
};
|
||||
|
||||
/* 获取客户列表数据 */
|
||||
pageCustomer({ progress: '4' })
|
||||
.then((result) => {
|
||||
data.value = result?.list.map((d) => {
|
||||
return {
|
||||
value: d.customerId,
|
||||
label: d.customerName
|
||||
};
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
message.error(e.message);
|
||||
});
|
||||
|
||||
/* 失去焦点 */
|
||||
const onBlur = () => {
|
||||
emit('blur');
|
||||
};
|
||||
|
||||
// 联动搜索
|
||||
const onSearch = (customerName) => {
|
||||
pageCustomer({ customerName }).then((res) => {
|
||||
console.log(res);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,46 @@
|
||||
<!-- 选择下拉框 -->
|
||||
<template>
|
||||
<a-select
|
||||
mode="multiple"
|
||||
show-search
|
||||
optionFilterProp="label"
|
||||
:options="data"
|
||||
allow-clear
|
||||
:value="value"
|
||||
:placeholder="placeholder"
|
||||
@update:value="updateValue"
|
||||
@blur="onBlur"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getDictionaryOptions } from '@/utils/common';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:value', value: string): void;
|
||||
(e: 'blur'): void;
|
||||
}>();
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
value?: string;
|
||||
placeholder?: string;
|
||||
}>(),
|
||||
{
|
||||
placeholder: '请选择已开发的端口'
|
||||
}
|
||||
);
|
||||
|
||||
// 字典数据
|
||||
const data = getDictionaryOptions('serverOpenPort');
|
||||
|
||||
/* 更新选中数据 */
|
||||
const updateValue = (value: string) => {
|
||||
emit('update:value', value);
|
||||
};
|
||||
|
||||
/* 失去焦点 */
|
||||
const onBlur = () => {
|
||||
emit('blur');
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,128 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space>
|
||||
<a-button
|
||||
type="primary"
|
||||
class="ele-btn-icon"
|
||||
v-permission="'oa:assets:save'"
|
||||
@click="add"
|
||||
>
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
<span>新建</span>
|
||||
</a-button>
|
||||
<a-button
|
||||
danger
|
||||
type="primary"
|
||||
class="ele-btn-icon"
|
||||
:v-role="`dev`"
|
||||
@click="removeBatch"
|
||||
v-if="props.selection.length > 0"
|
||||
>
|
||||
<template #icon>
|
||||
<DeleteOutlined />
|
||||
</template>
|
||||
<span>批量删除</span>
|
||||
</a-button>
|
||||
<a-input-search
|
||||
allow-clear
|
||||
v-model:value="searchText"
|
||||
placeholder="请输入搜索关键词"
|
||||
@search="search"
|
||||
@pressEnter="search"
|
||||
>
|
||||
<template #addonBefore>
|
||||
<a-select v-model:value="type" style="width: 120px; margin: -5px -12px">
|
||||
<a-select-option value="name">服务器名称</a-select-option>
|
||||
<a-select-option value="code">服务器IP</a-select-option>
|
||||
<a-select-option value="userId">用户ID</a-select-option>
|
||||
</a-select>
|
||||
</template>
|
||||
</a-input-search>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons-vue';
|
||||
import useSearch from '@/utils/use-search';
|
||||
import type { AssetsParam } from '@/api/oa/assets/model';
|
||||
// import SelectUser from '@/components/SelectUser/index.vue';
|
||||
import { ref, watch } from 'vue';
|
||||
import { assignObject } from 'ele-admin-pro';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: AssetsParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
}>();
|
||||
|
||||
const props = defineProps<{
|
||||
// 勾选的项目
|
||||
selection?: [];
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where } = useSearch<AssetsParam>({
|
||||
name: '',
|
||||
code: '',
|
||||
isExpire: '',
|
||||
userId: undefined
|
||||
});
|
||||
|
||||
// 下来选项
|
||||
const type = ref('name');
|
||||
// 搜索内容
|
||||
const searchText = ref('');
|
||||
|
||||
/* 搜索 */
|
||||
const search = () => {
|
||||
assignObject(where, {});
|
||||
if (type.value == 'name') {
|
||||
where.name = searchText.value;
|
||||
}
|
||||
if (type.value == 'code') {
|
||||
where.code = searchText.value;
|
||||
}
|
||||
if (type.value == 'userId') {
|
||||
const number = Number(searchText.value);
|
||||
if (number > 0) {
|
||||
where.userId = Number(searchText.value);
|
||||
}
|
||||
}
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
// const onSelect = (userId) => {
|
||||
// console.log(userId);
|
||||
// where.userId = userId;
|
||||
// console.log(where);
|
||||
// search();
|
||||
// };
|
||||
// const onClear = () => {
|
||||
// where.userId = undefined;
|
||||
// search();
|
||||
// };
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
// 批量删除
|
||||
const removeBatch = () => {
|
||||
emit('remove');
|
||||
};
|
||||
|
||||
/* 重置 */
|
||||
// const reset = () => {
|
||||
// resetFields();
|
||||
// search();
|
||||
// };
|
||||
|
||||
// 监听字典id变化
|
||||
watch(
|
||||
() => props.selection,
|
||||
() => {}
|
||||
);
|
||||
</script>
|
||||
@@ -0,0 +1,45 @@
|
||||
<!-- 角色选择下拉框 -->
|
||||
<template>
|
||||
<a-select
|
||||
show-search
|
||||
optionFilterProp="label"
|
||||
:options="data"
|
||||
allow-clear
|
||||
:value="value"
|
||||
:placeholder="placeholder"
|
||||
@update:value="updateValue"
|
||||
@blur="onBlur"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { getDictionaryOptions } from '@/utils/common';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:value', value: string): void;
|
||||
(e: 'blur'): void;
|
||||
}>();
|
||||
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
value?: string;
|
||||
placeholder?: string;
|
||||
}>(),
|
||||
{
|
||||
placeholder: '请选择年限'
|
||||
}
|
||||
);
|
||||
|
||||
// 字典数据
|
||||
const data = getDictionaryOptions('serverYears');
|
||||
|
||||
/* 更新选中数据 */
|
||||
const updateValue = (value: string) => {
|
||||
emit('update:value', value);
|
||||
};
|
||||
|
||||
/* 失去焦点 */
|
||||
const onBlur = () => {
|
||||
emit('blur');
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,329 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<div class="ele-body">
|
||||
<a-card :bordered="false">
|
||||
<!-- 表格 -->
|
||||
<ele-pro-table
|
||||
ref="tableRef"
|
||||
row-key="assetsId"
|
||||
:columns="columns"
|
||||
:height="tableHeight"
|
||||
:datasource="datasource"
|
||||
v-model:selection="selection"
|
||||
:customRow="customRow"
|
||||
:scroll="{ x: 800 }"
|
||||
>
|
||||
<template #toolbar>
|
||||
<search
|
||||
:selection="selection"
|
||||
@search="reload"
|
||||
@add="openEdit"
|
||||
@remove="removeBatch"
|
||||
/>
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'customer'">
|
||||
{{ record.nickname }}
|
||||
<!-- <div class="user-box">-->
|
||||
<!-- <a-avatar-->
|
||||
<!-- :size="30"-->
|
||||
<!-- :src="`${record.avatar}`"-->
|
||||
<!-- style="margin-right: 4px"-->
|
||||
<!-- >-->
|
||||
<!-- <template #icon>-->
|
||||
<!-- <UserOutlined />-->
|
||||
<!-- </template>-->
|
||||
<!-- </a-avatar>-->
|
||||
<!-- <div class="user-info">-->
|
||||
<!-- <span>{{ record.companyName }}</span>-->
|
||||
<!-- <span class="ele-text-placeholder">{{-->
|
||||
<!-- record.nickname-->
|
||||
<!-- }}</span>-->
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
</template>
|
||||
<template v-if="column.key === 'name'">
|
||||
<a-tooltip title="查看详情">
|
||||
<a href="#" @click="openInfo(record)">{{ record.name }}</a>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template v-if="column.key === 'code'">
|
||||
<a-tooltip title="服务器公网IP">
|
||||
{{ record.code }}
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template v-if="column.key === 'status'">
|
||||
<a-tag v-if="record.status === '0'" color="green">正常</a-tag>
|
||||
<a-tag v-if="record.status === '1'" color="red">停机</a-tag>
|
||||
</template>
|
||||
<template v-if="column.key === 'comments'">
|
||||
<a-tooltip :title="record.comments" placement="topLeft">
|
||||
{{ record.comments }}
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template v-if="column.key === 'endTime'">
|
||||
<div class="ele-text-info">{{
|
||||
toDateString(record.startTime, 'yyyy-MM-dd')
|
||||
}}</div>
|
||||
<div v-html="getEndTime(record.endTime)"></div>
|
||||
</template>
|
||||
<template v-if="column.key === 'createTime'">
|
||||
<a-tooltip :title="`${toDateString(record.createTime)}`">
|
||||
{{ timeAgo(record.createTime) }}
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a @click="openInfo(record)">详情</a>
|
||||
<a-divider type="vertical" />
|
||||
<a @click="openEdit(record)">修改</a>
|
||||
<a-divider type="vertical" />
|
||||
<a-popconfirm
|
||||
title="确定要删除此记录吗?"
|
||||
@confirm="remove(record)"
|
||||
>
|
||||
<a class="ele-text-danger">删除</a>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</ele-pro-table>
|
||||
</a-card>
|
||||
<!-- 编辑弹窗 -->
|
||||
<assets-edit v-model:visible="showEdit" :data="current" @done="reload" />
|
||||
<!-- 用户详情 -->
|
||||
<assets-info v-model:visible="showInfo" :data="current" @done="reload" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!--suppress TypeScriptValidateTypes -->
|
||||
<script lang="ts" setup>
|
||||
import { timeAgo } from 'ele-admin-pro';
|
||||
import { createVNode, computed, ref } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import {
|
||||
UserOutlined,
|
||||
ExclamationCircleOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
import type { EleProTable } from 'ele-admin-pro';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
ColumnItem
|
||||
} from 'ele-admin-pro/es/ele-pro-table/types';
|
||||
import { toDateString } from 'ele-admin-pro';
|
||||
import Search from './components/search.vue';
|
||||
import AssetsEdit from './components/assets-edit.vue';
|
||||
import AssetsInfo from './components/assets-info.vue';
|
||||
import { pageAssets, removeAssets, removeBatchAssets } from '@/api/oa/assets';
|
||||
import type { Assets, AssetsParam } from '@/api/oa/assets/model';
|
||||
import { getDictionaryOptions, getEndTime } from '@/utils/common';
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 是否显示资产详情
|
||||
const showInfo = ref(false);
|
||||
// 当前用户信息
|
||||
const brand = getDictionaryOptions('serverBrand');
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
key: 'index',
|
||||
width: 48,
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
hideInSetting: true,
|
||||
customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
|
||||
},
|
||||
{
|
||||
title: '服务器名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name'
|
||||
},
|
||||
{
|
||||
title: '服务器IP',
|
||||
dataIndex: 'code',
|
||||
key: 'code'
|
||||
},
|
||||
{
|
||||
title: '品牌',
|
||||
dataIndex: 'brand',
|
||||
filters: brand
|
||||
},
|
||||
// {
|
||||
// title: '备注',
|
||||
// dataIndex: 'comments',
|
||||
// key: 'comments',
|
||||
// ellipsis: true
|
||||
// },
|
||||
{
|
||||
title: '有效期',
|
||||
dataIndex: 'endTime',
|
||||
key: 'endTime',
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '所属客户',
|
||||
dataIndex: 'customer',
|
||||
key: 'customer'
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
sorter: true,
|
||||
key: 'status'
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
dataIndex: 'sortNumber',
|
||||
sorter: true,
|
||||
hideInTable: true
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
sorter: true,
|
||||
ellipsis: true,
|
||||
hideInTable: true,
|
||||
customRender: ({ text }) => toDateString(text)
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
hideInSetting: true
|
||||
}
|
||||
]);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<Assets[]>([]);
|
||||
// 当前编辑数据
|
||||
const current = ref<Assets | null>(null);
|
||||
// 是否显示编辑弹窗
|
||||
const showEdit = ref(false);
|
||||
|
||||
// 表格数据源
|
||||
const datasource: DatasourceFunction = ({
|
||||
page,
|
||||
limit,
|
||||
where,
|
||||
orders,
|
||||
filters
|
||||
}) => {
|
||||
if (filters) {
|
||||
where.brand = filters.brand;
|
||||
}
|
||||
return pageAssets({ ...where, ...orders, page, limit });
|
||||
};
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: AssetsParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
// 搜索是否展开
|
||||
const searchExpand = ref(false);
|
||||
|
||||
// 表格固定高度
|
||||
const fixedHeight = ref(false);
|
||||
|
||||
// 表格高度
|
||||
const tableHeight = computed(() => {
|
||||
return fixedHeight.value
|
||||
? searchExpand.value
|
||||
? 'calc(100vh - 618px)'
|
||||
: 'calc(100vh - 562px)'
|
||||
: void 0;
|
||||
});
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: Assets) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开用户详情弹窗 */
|
||||
const openInfo = (row?: Assets) => {
|
||||
current.value = row ?? null;
|
||||
showInfo.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: Assets) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeAssets(row.assetsId)
|
||||
.then((msg) => {
|
||||
hide();
|
||||
message.success(msg);
|
||||
reload();
|
||||
})
|
||||
.catch((e) => {
|
||||
hide();
|
||||
message.error(e.message);
|
||||
});
|
||||
};
|
||||
|
||||
/* 批量删除 */
|
||||
const removeBatch = () => {
|
||||
if (!selection.value.length) {
|
||||
message.error('请至少选择一条数据');
|
||||
return;
|
||||
}
|
||||
Modal.confirm({
|
||||
title: '提示',
|
||||
content: '确定要删除选中的记录吗?',
|
||||
icon: createVNode(ExclamationCircleOutlined),
|
||||
maskClosable: true,
|
||||
onOk: () => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeBatchAssets(selection.value.map((d) => d.assetsId))
|
||||
.then((msg) => {
|
||||
hide();
|
||||
message.success(msg);
|
||||
reload();
|
||||
})
|
||||
.catch((e) => {
|
||||
hide();
|
||||
message.error(e.message);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/* 自定义行属性 */
|
||||
const customRow = (record: Assets) => {
|
||||
return {
|
||||
// 行点击事件
|
||||
onClick: () => {
|
||||
// console.log(record);
|
||||
},
|
||||
// 行双击事件
|
||||
onDblclick: () => {
|
||||
openInfo(record);
|
||||
}
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'Assets'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.user-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.user-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user