Initial commit
This commit is contained in:
@@ -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('projectCategory');
|
||||
|
||||
/* 更新选中数据 */
|
||||
const updateValue = (value: string) => {
|
||||
emit('update:value', value);
|
||||
};
|
||||
|
||||
/* 失去焦点 */
|
||||
const onBlur = () => {
|
||||
emit('blur');
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,69 @@
|
||||
<!-- 角色选择下拉框 -->
|
||||
<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({ customerType: '' })
|
||||
.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) => {
|
||||
});
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<a-modal
|
||||
width="80%"
|
||||
:visible="visible"
|
||||
:confirm-loading="loading"
|
||||
:title="'富文本转MarkDown'"
|
||||
:body-style="{ paddingBottom: '8px' }"
|
||||
@update:visible="updateVisible"
|
||||
:footer="null"
|
||||
>
|
||||
<!-- 编辑器 -->
|
||||
<byte-md-editor
|
||||
v-model:value="content"
|
||||
:locale="zh_Hans"
|
||||
:plugins="plugins"
|
||||
height="600px"
|
||||
:editorConfig="{ lineNumbers: true }"
|
||||
/>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import ByteMdEditor from '@/components/ByteMdEditor/index.vue';
|
||||
// 中文语言文件
|
||||
import zh_Hans from 'bytemd/locales/zh_Hans.json';
|
||||
// 链接、删除线、复选框、表格等的插件
|
||||
import gfm from '@bytemd/plugin-gfm';
|
||||
// 插件的中文语言文件
|
||||
import zh_HansGfm from '@bytemd/plugin-gfm/locales/zh_Hans.json';
|
||||
// 预览界面的样式,这里用的 github 的 markdown 主题
|
||||
import 'github-markdown-css/github-markdown-light.css';
|
||||
import { copyText } from '@/utils/common';
|
||||
import { htmlToText } from "ele-admin-pro";
|
||||
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
}>();
|
||||
|
||||
// 编辑器内容,双向绑定
|
||||
const content = ref('');
|
||||
|
||||
// 插件
|
||||
const plugins = ref([
|
||||
gfm({
|
||||
locale: zh_HansGfm
|
||||
})
|
||||
]);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void;
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
/* 保存编辑 */
|
||||
// const save = () => {
|
||||
// copyText(content.value);
|
||||
// console.log('复制成功');
|
||||
// };
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
@@ -0,0 +1,488 @@
|
||||
<!-- 用户编辑弹窗 -->
|
||||
<template>
|
||||
<ele-modal
|
||||
width="75%"
|
||||
:visible="visible"
|
||||
:maskClosable="false"
|
||||
:confirm-loading="loading"
|
||||
:title="isUpdate ? '编辑项目' : '添加项目'"
|
||||
:body-style="{ paddingBottom: '8px' }"
|
||||
@update:visible="updateVisible"
|
||||
@ok="save"
|
||||
>
|
||||
<a-tabs type="card" v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="1" tab="基本信息">
|
||||
<a-form
|
||||
:label-col="{ md: { span: 2 }, sm: { span: 2 }, xs: { span: 24 } }"
|
||||
:wrapper-col="{
|
||||
md: { span: 20 },
|
||||
sm: { span: 20 },
|
||||
xs: { span: 24 }
|
||||
}"
|
||||
>
|
||||
<a-form-item label="项目名称" v-bind="validateInfos.projectName">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入项目名称"
|
||||
v-model:value="form.projectName"
|
||||
@blur="validate('projectName', { trigger: 'blur' }).catch(() => {})"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="项目编号" v-bind="validateInfos.projectCode">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入用户账号"
|
||||
v-model:value="form.projectCode"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="项目分类" v-bind="validateInfos.projectCategory">
|
||||
<category-select
|
||||
v-model:value="form.projectCategory"
|
||||
@blur="
|
||||
validate('projectCategory', { trigger: 'blur' }).catch(() => {})
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="所属客户" v-bind="validateInfos.customerId">
|
||||
<customer-select
|
||||
v-model:value="form.customerId"
|
||||
@blur="
|
||||
validate('customerId', { trigger: 'blur' }).catch(() => {})
|
||||
"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="图标">
|
||||
<ele-image-upload
|
||||
v-model:value="avatar"
|
||||
:item-style="{ width: '90px', height: '90px' }"
|
||||
:limit="1"
|
||||
@upload="onUploadAvatar"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="开发环境" v-bind="validateInfos.urlDev">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入开发环境地址"
|
||||
v-model:value="form.urlDev"
|
||||
@blur="validate('urlDev', { trigger: 'blur' }).catch(() => {})"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="账号密码" v-bind="validateInfos.account">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入开发环境账号密码"
|
||||
v-model:value="form.account"
|
||||
@blur="validate('account', { trigger: 'blur' }).catch(() => {})"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="生产环境" v-bind="validateInfos.url">
|
||||
<a-input
|
||||
allow-clear
|
||||
placeholder="请输入生产环境地址"
|
||||
v-model:value="form.url"
|
||||
@blur="validate('url', { trigger: 'blur' }).catch(() => {})"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态" v-bind="validateInfos.status">
|
||||
<status-select
|
||||
v-model:value="form.status"
|
||||
@blur="validate('status', { trigger: 'blur' }).catch(() => {})"
|
||||
/>
|
||||
</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-item label="项目简介" v-bind="validateInfos.comments">
|
||||
<a-textarea
|
||||
:rows="4"
|
||||
:maxlength="200"
|
||||
placeholder="请输入项目简介"
|
||||
v-model:value="form.comments"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="项目资料">
|
||||
<!-- 按钮 -->
|
||||
<div style="margin-bottom: 16px">
|
||||
<a-space>
|
||||
<a-button type="dashed" class="ele-btn-icon" @click="setContent">
|
||||
载入模板
|
||||
</a-button>
|
||||
<!-- <a-button type="dashed" class="ele-btn-icon" @click="showHtml">-->
|
||||
<!-- 获取html-->
|
||||
<!-- </a-button>-->
|
||||
<!-- <a-button type="dashed" class="ele-btn-icon" @click="showText">-->
|
||||
<!-- 获取文本-->
|
||||
<!-- </a-button>-->
|
||||
<!-- <a-button-->
|
||||
<!-- type="dashed"-->
|
||||
<!-- :danger="!disabled"-->
|
||||
<!-- class="ele-btn-icon"-->
|
||||
<!-- @click="toggleDisabled"-->
|
||||
<!-- >-->
|
||||
<!-- {{ disabled ? '启用' : '禁用' }}-->
|
||||
<!-- </a-button>-->
|
||||
<a-button type="dashed" @click="openMarkdown">转换工具</a-button>
|
||||
<a-button
|
||||
type="dashed"
|
||||
class="ele-btn-icon"
|
||||
@click="openUrl('https://p.haoii123.com/')"
|
||||
>
|
||||
一键排版
|
||||
</a-button>
|
||||
</a-space>
|
||||
</div>
|
||||
<!-- 编辑器 -->
|
||||
<tinymce-editor
|
||||
v-model:value="content"
|
||||
:disabled="disabled"
|
||||
:init="config"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="3" tab="项目附件">
|
||||
<ele-image-upload
|
||||
v-model:value="files"
|
||||
:limit="10"
|
||||
:drag="true"
|
||||
:multiple="true"
|
||||
@upload="onUploadFile"
|
||||
/>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
<!-- 转换工具 -->
|
||||
<markdown v-model:visible="showMarkdown" />
|
||||
</ele-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message, Modal } from 'ant-design-vue';
|
||||
import { assignObject, htmlToText } from 'ele-admin-pro';
|
||||
import CategorySelect from './category-select.vue';
|
||||
import StatusSelect from './status-select.vue';
|
||||
import CustomerSelect from './customer-select.vue';
|
||||
import Markdown from './markdown.vue';
|
||||
import { addProject, updateProject } from '@/api/oa/project';
|
||||
import type { Project } from '@/api/oa/project/model';
|
||||
import { createCode, openUrl } from '@/utils/common';
|
||||
import TinymceEditor from '@/components/TinymceEditor/index.vue';
|
||||
import type { ItemType } from 'ele-admin-pro/es/ele-image-upload/types';
|
||||
import { uploadFile } from '@/api/system/file';
|
||||
import { FILE_SERVER } from '@/config/setting';
|
||||
|
||||
const useForm = Form.useForm;
|
||||
// 是否是修改
|
||||
const isUpdate = ref(false);
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: Project | null;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void;
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
// 提交状态
|
||||
const loading = ref(false);
|
||||
const activeKey = ref('1');
|
||||
const content = ref('');
|
||||
const disabled = ref(false);
|
||||
const showMarkdown = ref(false);
|
||||
const editorRef = ref<InstanceType<typeof TinymceEditor> | null>(null);
|
||||
|
||||
// 用户信息
|
||||
const form = reactive<Project>({
|
||||
projectCode: `X` + createCode(),
|
||||
projectName: '',
|
||||
projectAvatar: '',
|
||||
projectCategory: undefined,
|
||||
urlDev: '',
|
||||
urlAdmin: '',
|
||||
account: '',
|
||||
comments: '',
|
||||
content: '',
|
||||
sortNumber: 100,
|
||||
customerName: '',
|
||||
customerId: undefined,
|
||||
status: '0',
|
||||
projectId: 0
|
||||
});
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 表单验证规则
|
||||
const rules = reactive({
|
||||
projectName: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请输入项目名称',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
projectCode: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请输入项目编号',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
// projectAvatar: [
|
||||
// {
|
||||
// required: true,
|
||||
// type: 'string',
|
||||
// message: '请上传项目图标',
|
||||
// trigger: 'blur'
|
||||
// }
|
||||
// ],
|
||||
projectCategory: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '请选择项目分类',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
customerId: [
|
||||
{
|
||||
required: true,
|
||||
type: 'number',
|
||||
message: '请选择所属客户',
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
status: [
|
||||
{
|
||||
required: true,
|
||||
type: 'string',
|
||||
message: '项目状态',
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
const { resetFields, validate, validateInfos } = useForm(form, rules);
|
||||
|
||||
// 项目图标
|
||||
const avatar = ref([]);
|
||||
|
||||
const onUploadAvatar = (d: ItemType) => {
|
||||
uploadFile(<File>d.file)
|
||||
.then((result) => {
|
||||
console.log(result);
|
||||
form.projectAvatar = result.path;
|
||||
message.success('上传成功');
|
||||
})
|
||||
.catch((e) => {
|
||||
message.error(e.message);
|
||||
});
|
||||
};
|
||||
|
||||
// 已上传数据
|
||||
const files = ref([]);
|
||||
|
||||
const onUploadFile = (d: ItemType) => {
|
||||
uploadFile(<File>d.file)
|
||||
.then((result) => {
|
||||
console.log(result);
|
||||
form.projectAvatar = result.path;
|
||||
message.success('上传成功');
|
||||
})
|
||||
.catch((e) => {
|
||||
message.error(e.message);
|
||||
});
|
||||
};
|
||||
|
||||
/* 修改编辑器内容 */
|
||||
const setContent = () => {
|
||||
content.value = [
|
||||
'<div style="text-align: center;color: #fff;background-image: linear-gradient(-90deg, rgb(62,119,255), rgb(159,98,212), rgb(255,78,170));padding: 32px 0;">',
|
||||
' <div style="font-size: 28px;margin-bottom: 16px;">项目资料模板</div>',
|
||||
' <div style="font-size:18px">通过设置常用模板可以加快工作效率哦!</div>',
|
||||
'</div><br/>'
|
||||
].join('');
|
||||
};
|
||||
|
||||
/* 获取编辑器内容 */
|
||||
const showHtml = () => {
|
||||
Modal.info({
|
||||
maskClosable: true,
|
||||
content: content.value
|
||||
});
|
||||
};
|
||||
|
||||
/* 获取编辑器纯文本内容 */
|
||||
const showText = () => {
|
||||
Modal.info({
|
||||
maskClosable: true,
|
||||
content: htmlToText(content.value)
|
||||
});
|
||||
};
|
||||
|
||||
/* 禁用启用切换 */
|
||||
const toggleDisabled = () => {
|
||||
disabled.value = !disabled.value;
|
||||
};
|
||||
|
||||
/* 打开用户详情弹窗 */
|
||||
const openMarkdown = () => {
|
||||
showMarkdown.value = true;
|
||||
};
|
||||
|
||||
const config = ref({
|
||||
height: 520,
|
||||
// 自定义文件上传(这里使用把选择的文件转成 blob 演示)
|
||||
file_picker_callback: (callback: any, _value: any, meta: any) => {
|
||||
const input = document.createElement('input');
|
||||
input.setAttribute('type', 'file');
|
||||
// 设定文件可选类型
|
||||
if (meta.filetype === 'image') {
|
||||
input.setAttribute('accept', 'image/*');
|
||||
} else if (meta.filetype === 'media') {
|
||||
input.setAttribute('accept', 'video/*');
|
||||
}
|
||||
input.onchange = () => {
|
||||
const file = input.files?.[0];
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
if (meta.filetype === 'media') {
|
||||
if (!file.type.startsWith('video/')) {
|
||||
editorRef.value?.alert({ content: '只能选择视频文件' });
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (file.size / 1024 / 1024 > 20) {
|
||||
editorRef.value?.alert({ content: '大小不能超过 20MB' });
|
||||
return;
|
||||
}
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
if (e.target?.result != null) {
|
||||
const blob = new Blob([e.target.result], { type: file.type });
|
||||
callback(URL.createObjectURL(blob));
|
||||
}
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
};
|
||||
input.click();
|
||||
}
|
||||
});
|
||||
|
||||
/* 上传事件 */
|
||||
const uploadHandler = (file: File) => {
|
||||
const item: ItemType = {
|
||||
file,
|
||||
uid: (file as any).uid,
|
||||
name: file.name,
|
||||
progress: 0,
|
||||
status: undefined
|
||||
};
|
||||
console.log(item);
|
||||
if (!file.type.startsWith('image')) {
|
||||
message.error('只能选择图片');
|
||||
return;
|
||||
}
|
||||
if (file.size / 1024 / 1024 > 2) {
|
||||
message.error('大小不能超过 2MB');
|
||||
return;
|
||||
}
|
||||
item.url = window.URL.createObjectURL(file);
|
||||
images.value.push(item);
|
||||
};
|
||||
|
||||
|
||||
/* 上传 item */
|
||||
const onUpload = ({ file }) => {
|
||||
// const item = images.value.find((t) => t.uid === d.uid) ?? d;
|
||||
// console.log('item:', item);
|
||||
// 模拟上传
|
||||
// item.status = 'uploading';
|
||||
// item.progress = 20;
|
||||
uploadFile(file).then((res) => {
|
||||
message.success('上传成功');
|
||||
console.log(res);
|
||||
});
|
||||
// const timer = setInterval(() => {
|
||||
// if (item.progress == null) {
|
||||
// item.progress = 20;
|
||||
// } else {
|
||||
// item.progress += 20;
|
||||
// }
|
||||
// if (item.progress === 100) {
|
||||
// item.status = 'done';
|
||||
// clearInterval(timer);
|
||||
// }
|
||||
// }, 1000);
|
||||
};
|
||||
|
||||
/* 保存编辑 */
|
||||
const save = () => {
|
||||
validate()
|
||||
.then(() => {
|
||||
loading.value = true;
|
||||
// 处理文章内容
|
||||
form.content = content.value;
|
||||
const data = {
|
||||
...form
|
||||
};
|
||||
// 转字符串
|
||||
const saveOrUpdate = isUpdate.value ? updateProject : addProject;
|
||||
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) {
|
||||
form.projectCode = `X` + createCode();
|
||||
if (props.data) {
|
||||
loading.value = false;
|
||||
assignObject(form, props.data);
|
||||
if (props.data?.content != null) {
|
||||
content.value = props.data?.content;
|
||||
}
|
||||
if (form.projectCode == '') {
|
||||
form.projectCode = `X` + createCode();
|
||||
}
|
||||
// 项目图标赋值
|
||||
avatar.value = [];
|
||||
if(props.data.projectAvatar){
|
||||
avatar.value.push({ uid:1, url: FILE_SERVER + props.data.projectAvatar, status: 'done' });
|
||||
}
|
||||
isUpdate.value = true;
|
||||
} else {
|
||||
isUpdate.value = false;
|
||||
}
|
||||
} else {
|
||||
resetFields();
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<style lang="less"></style>
|
||||
@@ -0,0 +1,236 @@
|
||||
<!-- 用户编辑弹窗 -->
|
||||
<template>
|
||||
<a-drawer
|
||||
:width="width"
|
||||
:visible="visible"
|
||||
:confirm-loading="loading"
|
||||
:title="'项目详情'"
|
||||
:body-style="{ paddingBottom: '8px' }"
|
||||
@update:visible="updateVisible"
|
||||
:footer="null"
|
||||
>
|
||||
<a-row :gutter="16" type="flex" justify="space-around">
|
||||
<a-col :span="4">
|
||||
<div class="project-card-head">
|
||||
<div class="project-avatar">
|
||||
<a-image
|
||||
v-if="project.projectAvatar"
|
||||
:src="`https://file.wsdns.cn/${project.projectAvatar}`"
|
||||
class="avatar"
|
||||
/>
|
||||
<a-avatar v-else :size="100">
|
||||
<template #icon>
|
||||
<AntDesignOutlined />
|
||||
</template>
|
||||
</a-avatar>
|
||||
</div>
|
||||
<a-tooltip title="双击切换全屏">
|
||||
<h4 class="project-title" @dblclick="onFullscreen">
|
||||
{{ project.projectName }}
|
||||
</h4>
|
||||
</a-tooltip>
|
||||
<!-- <div class="progress">-->
|
||||
<!-- <a-progress-->
|
||||
<!-- :width="60"-->
|
||||
<!-- type="circle"-->
|
||||
<!-- :steps="5"-->
|
||||
<!-- :percent="project.progress * 2"-->
|
||||
<!-- />-->
|
||||
<!-- <small class="ele-text-placeholder">项目进度</small>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="progress">-->
|
||||
<!-- <ele-qr-code-svg :value="project.projectName" :size="120" />-->
|
||||
<!-- <small class="ele-text-placeholder">手机扫一扫</small>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :span="19">
|
||||
<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 bordered>
|
||||
<a-descriptions-item :span="2" label="项目名称">
|
||||
{{ project.projectName }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="项目进度">
|
||||
<a-progress :percent="project.progress * 2" :steps="5" />
|
||||
<!-- <a-tag v-if="project.status === '0'" color="green">正常</a-tag>-->
|
||||
<!-- <a-tag v-if="project.status === '1'" color="red">禁用</a-tag>-->
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="项目编号">
|
||||
<div style="min-width: 90px">{{ project.projectCode }}</div>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="项目分类">
|
||||
{{ project.projectCategory }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="点击次数">
|
||||
{{ project.views }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item :span="2" label="客户名称">
|
||||
{{ project.customerName }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item :span="1" label="联系人">
|
||||
{{ project.comments }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item :span="2" label="开发环境">
|
||||
<a href="#" @click="openUrl(project.urlDev)">
|
||||
{{ project.urlDev }}
|
||||
</a>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item :span="1" label="账号">
|
||||
{{ project.account }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item :span="2" label="生产环境">
|
||||
<a href="#" @click="openUrl(project.url)">
|
||||
{{ project.url }}
|
||||
</a>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item :span="1" label="密码">
|
||||
<span>gxwebsoft.com</span>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item :span="3" label="项目简介">
|
||||
{{ project.comments }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</div>
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="1" tab="项目资料">
|
||||
<div class="content" v-html="content"></div>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="项目附件">
|
||||
<div class="content">附件</div>
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-form>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { Form, message } from 'ant-design-vue';
|
||||
import { assignObject, toggleFullscreen } from 'ele-admin-pro';
|
||||
import type { Project } from '@/api/oa/project/model';
|
||||
import { htmlToText } from 'ele-admin-pro';
|
||||
import { AntDesignOutlined } from '@ant-design/icons-vue';
|
||||
import { openUrl } from '@/utils/common';
|
||||
|
||||
const useForm = Form.useForm;
|
||||
|
||||
const props = defineProps<{
|
||||
// 弹窗是否打开
|
||||
visible: boolean;
|
||||
// 修改回显的数据
|
||||
data?: Project | null;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'done'): void;
|
||||
(e: 'update:visible', visible: boolean): void;
|
||||
}>();
|
||||
|
||||
// 用户信息
|
||||
const project = reactive<Project>({
|
||||
createTime: '',
|
||||
projectName: '',
|
||||
projectCode: '',
|
||||
comments: '',
|
||||
projectCategory: '',
|
||||
projectAvatar: '',
|
||||
projectType: '',
|
||||
url: '',
|
||||
urlDev: '',
|
||||
urlAdmin: '',
|
||||
account: '',
|
||||
annualFee: '',
|
||||
money: '',
|
||||
views: '',
|
||||
content: '',
|
||||
progress: '',
|
||||
customerId: undefined,
|
||||
customerName: '',
|
||||
realMoney: '',
|
||||
qrcode: '',
|
||||
sortNumber: undefined,
|
||||
status: undefined,
|
||||
projectId: 0
|
||||
});
|
||||
|
||||
// 请求状态
|
||||
const loading = ref(true);
|
||||
|
||||
const activeKey = ref('1');
|
||||
|
||||
const { resetFields } = useForm(project);
|
||||
|
||||
const content = ref('');
|
||||
|
||||
/* 更新visible */
|
||||
const updateVisible = (value: boolean) => {
|
||||
emit('update:visible', value);
|
||||
};
|
||||
|
||||
// 富文本处理
|
||||
const showHtml = (str) => {
|
||||
return str
|
||||
.replace(str ? /&(?!#?\w+;)/g : /&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, "'")
|
||||
.replace(/&nbsp;/g, '\u3000');
|
||||
};
|
||||
|
||||
/* 全屏切换 */
|
||||
const width = ref('75%');
|
||||
const onFullscreen = () => {
|
||||
try {
|
||||
width.value = width.value == '100%' ? '75%' : '100%';
|
||||
toggleFullscreen();
|
||||
} catch (e) {
|
||||
message.error('您的浏览器不支持全屏模式');
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
if (props.data) {
|
||||
loading.value = false;
|
||||
content.value = showHtml(props.data.content);
|
||||
assignObject(project, props.data);
|
||||
}
|
||||
} else {
|
||||
resetFields();
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<style lang="less">
|
||||
.tab-pane {
|
||||
min-height: 100px;
|
||||
}
|
||||
.content img {
|
||||
max-width: 95%;
|
||||
}
|
||||
.project-card-head {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-project: center;
|
||||
flex-direction: column;
|
||||
padding-top: 0px;
|
||||
}
|
||||
.project-avatar .avatar {
|
||||
width: 180px;
|
||||
}
|
||||
.progress {
|
||||
margin-top: 250px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-project: center;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,74 @@
|
||||
<!-- 搜索表单 -->
|
||||
<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.projectName"
|
||||
placeholder="请输入项目名称"
|
||||
allow-clear
|
||||
@pressEnter="search"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :sm="24" :xs="24">
|
||||
<a-form-item label="项目编号">
|
||||
<a-input
|
||||
v-model:value.trim="where.projectCode"
|
||||
placeholder="请输入项目编号"
|
||||
allow-clear
|
||||
@pressEnter="search"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :lg="6" :md="12" :sm="24" :xs="24">
|
||||
<a-form-item label="状态">
|
||||
<status-select
|
||||
v-model:value="where.status"
|
||||
@blur="validate('status', { trigger: 'blur' }).catch(() => {})"
|
||||
/>
|
||||
</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 { ProjectParam } from '@/api/oa/project/model';
|
||||
import StatusSelect from './status-select.vue';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: ProjectParam): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where, resetFields } = useSearch<ProjectParam>({
|
||||
projectName: '',
|
||||
projectCode: ''
|
||||
});
|
||||
|
||||
/* 搜索 */
|
||||
const search = () => {
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
/* 重置 */
|
||||
const reset = () => {
|
||||
resetFields();
|
||||
search();
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,89 @@
|
||||
<!-- 搜索表单 -->
|
||||
<template>
|
||||
<a-space :size="10" style="flex-wrap: wrap">
|
||||
<a-button type="primary" class="ele-btn-icon" @click="add">
|
||||
<template #icon>
|
||||
<plus-outlined />
|
||||
</template>
|
||||
<span>新建</span>
|
||||
</a-button>
|
||||
<a-button
|
||||
danger
|
||||
type="primary"
|
||||
class="ele-btn-icon"
|
||||
@click="removeBatch"
|
||||
v-role="'admin'"
|
||||
>
|
||||
<template #icon>
|
||||
<delete-outlined />
|
||||
</template>
|
||||
<span>删除</span>
|
||||
</a-button>
|
||||
<a-input-search
|
||||
allow-clear
|
||||
placeholder="请输入搜索关键词"
|
||||
v-model:value="searchText"
|
||||
@pressEnter="search"
|
||||
@search="search"
|
||||
>
|
||||
<template #addonBefore>
|
||||
<a-select v-model:value="type" style="width: 100px; margin: -5px -12px">
|
||||
<a-select-option value="projectName">项目名称</a-select-option>
|
||||
<a-select-option value="projectCode">项目标识</a-select-option>
|
||||
</a-select>
|
||||
</template>
|
||||
</a-input-search>
|
||||
<a-button type="link"> 高级搜索 </a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {
|
||||
PlusOutlined,
|
||||
SearchOutlined,
|
||||
DeleteOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
import useSearch from '@/utils/use-search';
|
||||
import type { ProjectParam } from '@/api/oa/project/model';
|
||||
import { ref } from 'vue';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search', where?: ProjectParam): void;
|
||||
(e: 'add'): void;
|
||||
(e: 'remove'): void;
|
||||
}>();
|
||||
|
||||
// 表单数据
|
||||
const { where } = useSearch<ProjectParam>({
|
||||
projectName: '',
|
||||
projectCode: ''
|
||||
});
|
||||
|
||||
// 下来选项
|
||||
const type = ref('projectName');
|
||||
// 搜索内容
|
||||
const searchText = ref('');
|
||||
|
||||
/* 搜索 */
|
||||
const search = () => {
|
||||
if (type.value == 'projectName') {
|
||||
where.projectName = searchText.value;
|
||||
where.projectCode = undefined;
|
||||
}
|
||||
if (type.value == 'projectCode') {
|
||||
where.projectCode = searchText.value;
|
||||
where.projectName = undefined;
|
||||
}
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
// 新增
|
||||
const add = () => {
|
||||
emit('add');
|
||||
};
|
||||
|
||||
// 批量删除
|
||||
const removeBatch = () => {
|
||||
emit('remove');
|
||||
};
|
||||
</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('projectStatus');
|
||||
|
||||
/* 更新选中数据 */
|
||||
const updateValue = (value: string) => {
|
||||
emit('update:value', value);
|
||||
};
|
||||
/* 失去焦点 */
|
||||
const onBlur = () => {
|
||||
emit('blur');
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<a-page-header :ghost="false" title="项目管理">
|
||||
<div class="ele-text-secondary"> 项目管理模块,多人协同开发项目。 </div>
|
||||
</a-page-header>
|
||||
<div class="ele-body">
|
||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||
<a-tabs type="card" tabPosition="top" v-model:activeKey="activeKey">
|
||||
<a-tab-pane v-for="(d, index) in data" :key="index" :tab="d.label">
|
||||
<list :type="d" />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-card>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import List from './list.vue';
|
||||
import { getDictionaryOptions } from '@/utils/common';
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(true);
|
||||
|
||||
// 当前选项卡
|
||||
const activeKey = ref(0);
|
||||
|
||||
// 获取字典数据
|
||||
const data = getDictionaryOptions('projectOwner');
|
||||
|
||||
/* 查询 */
|
||||
const query = () => {
|
||||
loading.value = true;
|
||||
};
|
||||
|
||||
query();
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'Customer'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.sys-organization-list {
|
||||
padding: 12px 6px;
|
||||
height: calc(100vh - 242px);
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,267 @@
|
||||
<template>
|
||||
<div class="ele-body">
|
||||
<!-- 表格 -->
|
||||
<ele-pro-table
|
||||
ref="tableRef"
|
||||
row-key="projectId"
|
||||
:columns="columns"
|
||||
:datasource="datasource"
|
||||
v-model:selection="selection"
|
||||
:scroll="{ x: 800 }"
|
||||
>
|
||||
<template #toolbar>
|
||||
<search @search="reload" @add="openEdit" @remove="removeBatch" />
|
||||
</template>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'projectName'">
|
||||
<a-avatar
|
||||
class="project-icon"
|
||||
:size="36"
|
||||
shape="square"
|
||||
:src="`https://file.wsdns.cn/${record.projectAvatar}`"
|
||||
>
|
||||
<template #icon>
|
||||
<AntDesignOutlined />
|
||||
</template>
|
||||
</a-avatar>
|
||||
<a-tooltip title="查看详情">
|
||||
<a href="#" @click="openInfo(record)">{{ record.projectName }}</a>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<template v-if="column.key === 'progress'">
|
||||
<a-progress :percent="record.progress * 2" :steps="5" />
|
||||
</template>
|
||||
<template v-if="column.key === 'status'">
|
||||
<div v-for="(dict, index) in projectStatus" :key="index">
|
||||
<a-tag :color="dict.comments" v-if="dict.value === record.status">{{
|
||||
dict.label
|
||||
}}</a-tag>
|
||||
</div>
|
||||
</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>
|
||||
|
||||
<!-- 编辑弹窗 -->
|
||||
<project-edit v-model:visible="showEdit" :data="current" @done="reload" />
|
||||
<!-- 用户详情 -->
|
||||
<project-info v-model:visible="showInfo" :data="current" @done="reload" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, createVNode, ref } from 'vue';
|
||||
import { message, Modal, SelectProps } from 'ant-design-vue';
|
||||
import {
|
||||
ExclamationCircleOutlined,
|
||||
AntDesignOutlined
|
||||
} 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 ProjectEdit from './components/project-edit.vue';
|
||||
import ProjectInfo from './components/project-info.vue';
|
||||
import { pageProject, removeProject, removeBatchProject } from '@/api/oa/project';
|
||||
import type { Project, ProjectParam } from '@/api/oa/project/model';
|
||||
import { listDictionaryData } from '@/api/system/dictionary-data';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import {getDictionaryOptions} from "@/utils/common";
|
||||
|
||||
const userStore = useUserStore();
|
||||
const props = defineProps<{
|
||||
// 机构 id
|
||||
type?: any;
|
||||
}>();
|
||||
|
||||
// 表格实例
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
// 是否显示资产详情
|
||||
const showInfo = ref(false);
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref<ColumnItem[]>([
|
||||
{
|
||||
key: 'index',
|
||||
width: 48,
|
||||
align: 'center',
|
||||
fixed: 'left',
|
||||
hideInSetting: true,
|
||||
customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
|
||||
},
|
||||
{
|
||||
title: '项目名称',
|
||||
dataIndex: 'projectName',
|
||||
key: 'projectName',
|
||||
width: 280,
|
||||
ellipsis: true,
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '项目简介',
|
||||
dataIndex: 'comments'
|
||||
},
|
||||
{
|
||||
title: '开发进度',
|
||||
dataIndex: 'progress',
|
||||
key: 'progress',
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '项目地址',
|
||||
dataIndex: 'url'
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '排序',
|
||||
dataIndex: 'sortNumber',
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime',
|
||||
sorter: true,
|
||||
ellipsis: true,
|
||||
customRender: ({ text }) => toDateString(text)
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 200,
|
||||
align: 'center',
|
||||
hideInSetting: true
|
||||
}
|
||||
]);
|
||||
|
||||
// 表格选中数据
|
||||
const selection = ref<Project[]>([]);
|
||||
|
||||
// 当前编辑数据
|
||||
const current = ref<Project | null>(null);
|
||||
|
||||
// 当前用户信息
|
||||
const loginUser = computed(() => userStore.info ?? {});
|
||||
|
||||
// 是否显示编辑弹窗
|
||||
const showEdit = ref(false);
|
||||
|
||||
/* 获取字典数据 */
|
||||
const projectStatus = getDictionaryOptions('projectStatus');
|
||||
|
||||
// 表格数据源
|
||||
const datasource: DatasourceFunction = ({ page, limit, where, orders }) => {
|
||||
// 搜索条件
|
||||
if (props.type.key === 'my') {
|
||||
where.userId = loginUser.value.userId;
|
||||
} else if (props.type.key === 'assist') {
|
||||
where.userId = loginUser.value.userId;
|
||||
} else if (props.type.key === 'all') {
|
||||
// 全部客户
|
||||
}
|
||||
return pageProject({ ...where, ...orders, page, limit });
|
||||
};
|
||||
|
||||
/* 搜索 */
|
||||
const reload = (where?: ProjectParam) => {
|
||||
selection.value = [];
|
||||
tableRef?.value?.reload({ where: where });
|
||||
};
|
||||
|
||||
/* 打开编辑弹窗 */
|
||||
const openEdit = (row?: Project) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
|
||||
/* 打开用户详情弹窗 */
|
||||
const openInfo = (row?: Project) => {
|
||||
current.value = row ?? null;
|
||||
showInfo.value = true;
|
||||
};
|
||||
|
||||
/* 删除单个 */
|
||||
const remove = (row: Project) => {
|
||||
const hide = message.loading('请求中..', 0);
|
||||
removeProject(row.projectId)
|
||||
.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);
|
||||
removeBatchProject(selection.value.map((d) => d.projectId))
|
||||
.then((msg) => {
|
||||
hide();
|
||||
message.success(msg);
|
||||
reload();
|
||||
})
|
||||
.catch((e) => {
|
||||
hide();
|
||||
message.error(e.message);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'Project'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.project-icon {
|
||||
margin-right: 10px;
|
||||
}
|
||||
.sys-org-table :deep(.ant-table-body) {
|
||||
overflow: auto !important;
|
||||
overflow: overlay !important;
|
||||
}
|
||||
|
||||
.sys-org-table :deep(.ant-table-pagination.ant-pagination) {
|
||||
padding: 0 4px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user