Commit cc0018b2 authored by wangjiancheng's avatar wangjiancheng

feat:项目管理

parent 175d0ce8
import request from '@/utils/request'
// 查询项目管理列表
export function listProject(query) {
return request({
url: '/system/project/list',
method: 'get',
params: query
})
}
// 查询项目管理详细
export function getProject(id) {
return request({
url: '/system/project/' + id,
method: 'get'
})
}
// 新增项目管理
export function addProject(data) {
return request({
url: '/system/project',
method: 'post',
data: data
})
}
// 修改项目管理
export function updateProject(data) {
return request({
url: '/system/project',
method: 'put',
data: data
})
}
// 删除项目管理
export function delProject(id) {
return request({
url: '/system/project/' + id,
method: 'delete'
})
}
// 查询草稿箱列表
export function listDraft(query) {
return request({
url: '/system/project/draft/list',
method: 'get',
params: query
})
}
// 新增草稿箱
export function addDraft(data) {
data.darft = '0'
return request({
url: '/system/project/draft',
method: 'post',
data: data
})
}
// 逻辑删除项目
export function logicRemove(id) {
return request({
url: '/system/project/logicRemove/' + id,
method: 'delete'
})
}
<template>
<div class="app-container">
<el-form ref="form" :model="form" :rules="rules" label-width="auto">
<el-form-item label="项目名称" prop="projectName">
<el-input v-model="form.projectName" placeholder="请输入项目名称" />
</el-form-item>
<el-form-item label="项目类型" prop="projectType">
<el-select v-model="form.projectType" placeholder="请选择项目类型" >
<el-option
v-for="dict in project_type"
:key="dict.value"
:label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="预计结束时间" prop="startDate">
<el-date-picker
v-model="form.startDate"
type="date"
placeholder="选择日期"
>
</el-date-picker>
</el-form-item>
<el-form-item label="预计开始时间" prop="endDate">
<el-date-picker
class="el-input"
v-model="form.endDate"
type="date"
placeholder="选择日期"
>
</el-date-picker>
</el-form-item>
<el-form-item label="项目经理" prop="projectManagerId">
<el-select v-model="form.projectManagerId" placeholder="请选择项目经理" >
<el-option
v-for="dict in managerOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="项目成员" prop="projectMemberIds">
<el-select v-model="form.projectMemberIds" placeholder="请选择项目成员" >
<el-option
v-for="dict in membersOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="项目成本" prop="projectCost">
<el-input v-model="form.projectCost" placeholder="请输入项目成本" ></el-input>
</el-form-item>
<el-form-item label="项目描述" prop="projectDescribe">
<el-input type="textarea" v-model="form.projectDescribe" placeholder="请输入项目描述" ></el-input>
</el-form-item>
<el-form-item label="项目状态" prop="projectStatus">
<el-select v-model="form.projectStatus" placeholder="请选择项目状态" >
<el-option
v-for="dict in project_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="项目附件" >
<el-upload
v-model:file-list="form.fileList"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
multiple
:on-preview="handlePreview"
:on-remove="handleRemove"
:before-remove="beforeRemove"
:limit="3"
:on-exceed="handleExceed"
>
<el-button type="text">上传附件</el-button>
</el-upload>
</el-form-item>
<el-form-item label="项目回款">
<el-select
v-model="form.repaymentCount"
placeholder="请选择项目回款笔数"
@change="updateRepaymentInputs"
>
<el-option
v-for="num in 10"
:key="num"
:label="num"
:value="num"
></el-option>
</el-select>
</el-form-item>
<el-form :model="form" label-width="120px">
<div v-for="(item, index) in form.repaymentDetails" :key="index">
<el-row>
<el-col :span="5">
<!-- 回款比例 -->
<el-form-item :label="'第 ' + (index + 1) + ' 笔'">
<el-input v-model="item.repaymentPercentage" suffix="%" ></el-input>
</el-form-item>
</el-col>
<el-col :span="5">
<!-- 回款条件 -->
<el-form-item>
<el-input v-model="item.repaymentCondition" ></el-input>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
</el-form>
<!-- 提交和保存草稿按钮 -->
<div>
<el-button type="primary" @click="handleSubmit" >提交</el-button>
<el-button type="primary" @click="saveDraft">保存草稿</el-button>
<el-button type="info" @click="reset">取消</el-button>
</div>
</div>
</template>
<script setup name="add">
import { listUser } from "../../api/system/user.js";
const { proxy } = getCurrentInstance();
const { project_status, project_type } = proxy.useDict('project_status', 'project_type');
const form = reactive({
projectName: '',
projectType: '',
startDate: '',
endDate: '',
departmentLeadId: '',
projectManagerId: '',
projectMemberIds: [],
projectCost: '',
projectDescribe: '',
projectStatus: '',
fileList: [],
repaymentCount: null,
repaymentDetails: []
})
const rules = ref({
projectName: [
{ required: true, message: '项目名称不能为空', trigger: 'blur' }
],
projectType: [
{ required: true, message: '项目类型不能为空', trigger: 'blur' }
],
startDate: [
{ required: true, message: '预计开始时间不能为空', trigger: 'blur' }
],
endDate: [
{ required: true, message: '预计结束时间不能为空', trigger: 'blur' }
]
})
const headOptions = ref([])
const managerOptions = ref([])
const membersOptions = ref([])
const getUserList = () => {
listUser().then(response => {
headOptions.value = response.rows.map(item => {
return {
value: item.userId,
label: item.nickName
}
})
managerOptions.value = response.rows.map(item => {
return {
value: item.userId,
label: item.nickName
}
})
membersOptions.value = response.rows.map(item => {
return {
value: item.userId,
label: item.nickName
}
})
})
}
// 提交表单
const handleSubmit = () => {
console.log(form)
}
// 保存草稿
const saveDraft = () => {
console.log(form)
}
// 重置表单
const resetForm = () => {
form.projectName = ''
form.projectType = ''
form.startDate = ''
form.endDate = ''
form.departmentLeadId = ''
form.projectManagerId = ''
form.projectMemberIds = []
form.projectCost = ''
form.projectDescribe = ''
form.projectStatus = ''
form.fileList = []
form.repaymentCount = ''
form.repaymentDetails = []
}
// 返回项目管理页面
const reset = () => {
// 返回项目
proxy.$router.push({ path: '/project' })
resetForm()
}
const updateRepaymentInputs = () => {
// 根据用户输入的回款笔数更新百分比输入框的数量
if (form.repaymentCount > 0) {
form.repaymentDetails = Array.from({ length: form.repaymentCount }, () => ({
repaymentPercentage: null, // 回款百分比
repaymentCondition: "" // 回款前置条件
}));
} else {
form.repaymentDetails = [];
}
}
// 删除附件相关事件
const handleRemove = (file, fileList) => {
console.log(file, fileList)
}
// 预览附件相关事件
const handlePreview = (file) => {
console.log(file)
}
// 上传附件数量限制
const handleExceed = (files, fileList) => {
this.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
}
// 上传附件删除相关事件
const beforeRemove = (file, fileList) => {
return this.$confirm(`确定移除 ${file.name}?`);
}
// 上传附件成功相关事件
// 在组件挂载时执行
onMounted(() => {
getUserList()
});
</script>
<style scoped lang="scss">
</style>
<template>
<div class="app-container">
<el-table v-loading="loading" :data="projectList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="项目编号" align="center" prop="projectNumber" />
<el-table-column label="项目名称" align="center" prop="projectName" />
<el-table-column label="项目类型" align="center" prop="projectType">
<template #default="scope">
<dict-tag :options="project_type" :value="scope.row.projectType"/>
</template>
</el-table-column>
<el-table-column label="预计开始时间" align="center" prop="startDate" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.startDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="预计结束时间" align="center" prop="endDate" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.endDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="事业部负责人" align="center" prop="departmentLeaderId" />
<el-table-column label="项目经理" align="center" prop="projectManagerId" />
<el-table-column label="项目成本" align="center" prop="projectCost" />
<el-table-column label="项目描述" align="center" prop="projectDescribe" />
<el-table-column label="项目状态" align="center" prop="projectStatus">
<template #default="scope">
<dict-tag :options="project_status" :value="scope.row.projectStatus"/>
</template>
</el-table-column>
<el-table-column label="立项时间" align="center" prop="createDate" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="更新时间" align="center" prop="updateDate" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.updateDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:project:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:project:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</div>
</template>
<script setup name="draft">
import { listProject,logicRemove} from "../../api/project/project.js";
const { proxy } = getCurrentInstance();
const { project_status, project_type } = proxy.useDict('project_status', 'project_type');
const projectList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
projectNumber: null,
projectName: null,
projectType: null,
departmentLeaderId: null,
projectManagerId: null,
projectStatus: null,
},
rules: {
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询项目管理列表 */
function getList() {
loading.value = true;
listProject(queryParams.value).then(response => {
projectList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
// 取消按钮
function cancel() {
open.value = false;
reset();
}
// 表单重置
function reset() {
form.value = {
id: null,
projectNumber: null,
projectName: null,
projectType: null,
startDate: null,
endDate: null,
departmentLeaderId: null,
projectManagerId: null,
projectCost: null,
projectDescribe: null,
projectStatus: null,
createDate: null,
updateDate: null,
draft: null,
delFlag: null
};
proxy.resetForm("projectRef");
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
}
/** 新增按钮操作 */
function handleAdd() {
// 跳转新增页面
proxy.$router.push({ path: '/project/opera/add' });
}
/** 修改按钮操作 */
function handleUpdate(row) {
proxy.$router.push({ path: '/project/opera/edit', query: { id: row.id } });
}
// 查看详情
function handleView(row) {
// 跳转详情页面
proxy.$router.push({ path: '/project/opera/view', query: { id: row.id } });
}
// 查看草稿箱列表
function handleDraft() {
// 跳转草稿箱页面
proxy.$router.push({ path: '/project/opera/draft' });
}
/** 逻辑删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value;
proxy.$modal.confirm('是否确认删除项目管理编号为"' + _ids + '"的数据项?').then(function() {
return logicRemove(_ids);
}).then(() => {
getList();
proxy.$modal.msgSuccess("删除成功");
}).catch(() => {});
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('system/project/export', {
...queryParams.value
}, `project_${new Date().getTime()}.xlsx`)
}
getList();
</script>
<style scoped lang="scss">
</style>
<template>
<div class="app-container">
<el-form ref="form" :model="form" :rules="rules" label-width="auto">
<el-form-item label="项目编号">
<el-input v-model="form.projectNumber" placeholder="请输入项目编号" disabled/>
</el-form-item>
<el-form-item label="项目名称">
<el-input v-model="form.projectName" placeholder="请输入项目名称"/>
</el-form-item>
<el-form-item label="项目类型">
<el-select v-model="form.projectType" placeholder="请选择项目类型" >
<el-option
v-for="dict in project_type"
:key="dict.value"
:label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="预计结束时间">
<el-date-picker
v-model="form.startDate"
type="date"
placeholder="选择日期"
/>
</el-form-item>
<el-form-item label="预计开始时间">
<el-date-picker
v-model="form.endDate"
type="date"
placeholder="选择日期"
/>
</el-form-item>
<el-form-item label="事业部门负责人">
<el-select v-model="form.departmentLeadId" placeholder="请选择事业部门负责人" disabled>
<el-option
v-for="dict in headOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="项目经理">
<el-select v-model="form.projectManagerId" placeholder="请选择项目经理" disabled>
<el-option
v-for="dict in managerOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="项目成员">
<el-select v-model="form.projectMemberIds" placeholder="请选择项目成员">
<el-option
v-for="dict in membersOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="项目成本">
<el-input v-model="form.projectCost" placeholder="请输入项目成本" />
</el-form-item>
<el-form-item label="项目描述">
<el-input v-model="form.projectDescribe" placeholder="请输入项目描述" />
</el-form-item>
<el-form-item label="项目状态">
<el-select v-model="form.projectStatus" placeholder="请选择项目状态">
<el-option
v-for="dict in project_status"
:key="dict.value"
:label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="项目附件">
<el-upload
class="upload-demo"
action="https://jsonplaceholder.typicode.com/posts/"
:on-preview="handlePreview"
:on-remove="handleRemove"
:before-remove="beforeRemove"
:file-list="form.fileList"
:on-change="handleChange"
:limit="3"
:on-exceed="handleExceed"
:auto-upload="false"
:on-success="handleSuccess">
<el-button size="default" type="text">点击上传</el-button>
</el-upload>
</el-form-item>
<el-form-item label="项目回款笔数">
<el-select
v-model="form.repaymentCount"
placeholder="请选择项目回款笔数"
@change="updateRepaymentInputs"
>
<el-option
v-for="num in 10"
:key="num"
:label="num"
:value="num"
></el-option>
</el-select>
</el-form-item>
<el-form :model="form" label-width="120px">
<div v-for="(item, index) in form.repaymentDetails" :key="index">
<el-row>
<el-col :span="5">
<!-- 回款比例 -->
<el-form-item :label="'第 ' + (index + 1) + ' 笔'">
<el-input v-model="item.repaymentPercentage" suffix="%"></el-input>
</el-form-item>
</el-col>
<el-col :span="5">
<!-- 回款条件 -->
<el-form-item>
<el-input v-model="item.repaymentCondition"></el-input>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
</el-form>
<div class="dialog-footer">
<el-button @click="cancel">取 消</el-button>
<el-button type="primary" @click="submitForm">确 定</el-button>
</div>
</div>
</template>
<script setup name="edit">
import {getProject} from "../../api/project/project.js";
import {listUser} from "../../api/system/user.js";
const { proxy } = getCurrentInstance();
const { project_status, project_type } = proxy.useDict('project_status', 'project_type');
const headOptions = ref([])
const managerOptions = ref([])
const membersOptions = ref([])
const repaymentInputs = ref([])
const form = ref({
projectNumber: '',
projectName: '',
projectType: '',
startDate: '',
endDate: '',
departmentLeadId: '',
projectManagerId: '',
projectMemberIds: [],
projectCost: '',
projectDescribe: '',
projectStatus: '',
fileList: [],
repaymentCount: '',
repaymentDetails: [],
})
const rules = ref({
projectName: [
{ required: true, message: '项目名称不能为空', trigger: 'blur' }
],
projectType: [
{ required: true, message: '项目类型不能为空', trigger: 'blur' }
],
startDate: [
{ required: true, message: '预计开始时间不能为空', trigger: 'blur' }
],
endDate: [
{ required: true, message: '预计结束时间不能为空', trigger: 'blur' }
]
})
const getUserList = () => {
listUser().then(response => {
headOptions.value = response.rows.map(item => {
return {
value: item.userId,
label: item.nickName
}
})
managerOptions.value = response.rows.map(item => {
return {
value: item.userId,
label: item.nickName
}
})
membersOptions.value = response.rows.map(item => {
return {
value: item.userId,
label: item.nickName
}
})
})
}
let projectId = null;
function getProjectManage(){
projectId = proxy.$route.query.id;
getProject(projectId).then(response => {
form.value = response.data;
})
}
const updateRepaymentInputs = () => {
// 根据输入的回款笔数更新动态生成的回款输入框
const count = parseInt(form.value.repaymentCount)
if (isNaN(count)) {
return
}
repaymentInputs.value = []
for (let i = 0; i < count; i++) {
repaymentInputs.value.push({
repaymentPercentage: '',
repaymentCondition: ''
})
}
}
// 获取 typeName 的方法
const getTypeName = (id) => {
//const type = project_type.find(item => item.id === id);
// return type ? type.name : '未知类型';
}
const handleChange = (file, fileList) => {
console.log(file, fileList)
}
const handleRemove = (file, fileList) => {
console.log(file, fileList)
}
const handleSuccess = (response, file, fileList) => {
console.log(response, file, fileList)
}
const handlePreview = (file) => {
console.log(file)
}
const handleExceed = (files, fileList) => {
proxy.$message.warning(`当前限制选择 3 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
}
const cancel = () => {
proxy.$router.push({ path: '/project' })
resetForm()
}
onMounted(() => {
getProjectManage()
getUserList()
})
</script>
<style scoped lang="scss">
</style>
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="项目名称" prop="projectName">
<el-input
v-model="queryParams.projectName"
placeholder="请输入项目名称"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="项目类型" prop="projectType">
<el-select v-model="queryParams.projectType" placeholder="请选择项目类型" clearable>
<el-option
v-for="dict in project_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="事业部负责人" prop="departmentLeaderId">
<el-input
v-model="queryParams.departmentLeaderId"
placeholder="请输入事业部负责人"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="项目经理" prop="projectManagerId">
<el-input
v-model="queryParams.projectManagerId"
placeholder="请输入项目经理"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="项目状态" prop="projectStatus">
<el-select v-model="queryParams.projectStatus" placeholder="请选择项目状态" clearable>
<el-option
v-for="dict in project_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['system:project:add']"
>项目立项</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Delete"
:disabled="single"
@click="handleDraft"
v-hasPermi="['system:project:draft']"
>草稿箱</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['system:project:export']"
>导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="projectList">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="项目编号" align="center" prop="projectNumber" />
<el-table-column label="项目名称" align="center" prop="projectName" />
<el-table-column label="项目类型" align="center" prop="projectType">
<template #default="scope">
<dict-tag :options="project_type" :value="scope.row.projectType"/>
</template>
</el-table-column>
<el-table-column label="预计开始时间" align="center" prop="startDate" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.startDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="预计结束时间" align="center" prop="endDate" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.endDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="事业部负责人" align="center" prop="departmentLeaderName" />
<el-table-column label="项目经理" align="center" prop="projectManagerName"/>
<el-table-column label="项目成本" align="center" prop="projectCost" />
<el-table-column label="项目状态" align="center" prop="projectStatus">
<template #default="scope">
<dict-tag :options="project_status" :value="scope.row.projectStatus"/>
</template>
</el-table-column>
<el-table-column label="立项时间" align="center" prop="createDate" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createDate, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="更新时间" align="center" prop="updateDate" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.updateDate, '{y}-{m}-{d}') || '-'}}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="250">
<template #default="scope">
<el-button link type="primary" icon="View" @click="handleView(scope.row)" v-hasPermi="['system:project:view']">详情</el-button>
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:project:edit']">编辑</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:project:logicRemove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</div>
</template>
<script setup name="Project">
import { listProject,logicRemove} from "../../api/project/project.js";
const { proxy } = getCurrentInstance();
const { project_status, project_type } = proxy.useDict('project_status', 'project_type');
const projectList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
projectNumber: null,
projectName: null,
projectType: null,
departmentLeaderId: null,
projectManagerId: null,
projectStatus: null,
},
rules: {
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询项目管理列表 */
function getList() {
loading.value = true;
listProject(queryParams.value).then(response => {
projectList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
// 取消按钮
function cancel() {
open.value = false;
reset();
}
// 表单重置
function reset() {
form.value = {
id: null,
projectNumber: null,
projectName: null,
projectType: null,
startDate: null,
endDate: null,
departmentLeaderId: null,
projectManagerId: null,
projectCost: null,
projectDescribe: null,
projectStatus: null,
createDate: null,
updateDate: null,
draft: null,
delFlag: null
};
proxy.resetForm("projectRef");
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
}
/** 新增按钮操作 */
function handleAdd() {
// 跳转新增页面
proxy.$router.push({ path: '/project/opera/add' });
}
/** 修改按钮操作 */
function handleUpdate(row) {
proxy.$router.push({ path: '/project/opera/edit', query: { id: row.id } });
}
// 查看详情
function handleView(row) {
// 跳转详情页面
proxy.$router.push({ path: '/project/opera/view', query: { id: row.id } });
}
// 查看草稿箱列表
function handleDraft() {
// 跳转草稿箱页面
proxy.$router.push({ path: '/project/opera/draft' });
}
/** 逻辑删除按钮操作 */
function handleDelete(row) {
const _ids = row.id || ids.value;
proxy.$modal.confirm('是否确认删除项目管理编号为"' + _ids + '"的数据项?').then(function() {
return logicRemove(_ids);
}).then(() => {
getList();
proxy.$modal.msgSuccess("删除成功");
}).catch(() => {});
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('system/project/export', {
...queryParams.value
}, `project_${new Date().getTime()}.xlsx`)
}
getList();
</script>
<template>
<div class="app-container">
<el-form :model="form" label-width="auto">
<el-form-item label="项目编号" prop="projectNumber" >
<el-input v-model="form.projectNumber" placeholder="请输入项目编号" disabled></el-input>
</el-form-item>
<el-form-item label="项目名称" prop="projectName" >
<el-input v-model="form.projectName" placeholder="请输入项目名称" readonly></el-input>
</el-form-item>
<el-form-item label="项目类型" prop="projectType" >
<el-select
v-model="form.projectType"
placeholder="请选择项目类型"
readonly>
<el-option
v-for="dict in project_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="开始时间">
<el-date-picker
v-model="form.startDate"
type="date"
placeholder="选择日期"
readonly
></el-date-picker>
</el-form-item>
<el-form-item label="结束时间">
<el-date-picker
v-model="form.endDate"
type="date"
placeholder="选择日期"
readonly
></el-date-picker>
</el-form-item>
<el-form-item label="部门负责人">
<el-input
v-model="form.departmentLeaderName"
placeholder="请输入部门负责人名称"
disabled
></el-input>
</el-form-item>
<el-form-item label="项目经理">
<el-select
v-model="form.projectManagerId"
placeholder="请选择项目经理"
readonly>
<el-option
v-for="dict in managerOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="项目成员">
<el-select
v-model="form.projectMemberIds"
multiple
placeholder="请选择项目成员"
readonly>
<el-option
v-for="dict in membersOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="项目成本(元)">
<el-input
v-model="form.projectCost"
placeholder="请输入项目成本"
readonly
></el-input>
</el-form-item>
<el-form-item label="项目描述">
<el-input
v-model="form.projectDescribe"
type="textarea"
placeholder="请输入项目描述"
readonly
></el-input>
</el-form-item>
<el-form-item label="项目状态">
<el-select
v-model="form.projectStatus"
placeholder="请选择项目状态"
>
<el-option
v-for="dict in project_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="项目附件">
<!-- 展示已上传的附件 -->
<ul>
<li v-for="(file, index) in fileList" :key="index">
<a :href="file.url" target="_blank">{{ file.name }}</a>
</li>
</ul>
</el-form-item>
<el-form-item label="项目回款笔数">
<el-input v-model="form.repaymentCount" readonly></el-input>
</el-form-item>
<el-form :model="form" label-width="120px">
<div v-for="(item, index) in form.repaymentDetails" :key="index">
<el-row>
<el-col :span="5">
<!-- 回款比例 -->
<el-form-item :label="'第 ' + (index + 1) + ' 笔'">
<el-input v-model="item.repaymentPercentage" suffix="%" readonly></el-input>
</el-form-item>
</el-col>
<el-col :span="5">
<!-- 回款条件 -->
<el-form-item>
<el-input v-model="item.repaymentCondition" readonly></el-input>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
</el-form>
<div>
<el-button @click="reset">取消</el-button>
</div>
</div>
</template>
<script setup>
import { getProject } from "../../api/project/project.js";
import {listUser} from "../../api/system/user.js";
const { proxy } = getCurrentInstance();
const { project_status, project_type } = proxy.useDict('project_status', 'project_type');
const form = ref({
projectNumber: '',
projectName: '',
projectType: '',
startDate: '',
endDate: '',
departmentLeaderName: '',
departmentLeadId: '',
projectManagerId: '',
projectMemberIds: [],
projectCost: '',
projectDescribe: '',
projectStatus: '',
fileList: [],
repaymentCount: '',
repaymentDetails: [],
})
const repaymentDetails = ref([])
const headOptions = ref([])
const managerOptions = ref([])
const membersOptions = ref([])
const getUserList = () => {
listUser().then(response => {
headOptions.value = response.rows.map(item => {
return {
value: item.userId,
label: item.nickName
}
})
managerOptions.value = response.rows.map(item => {
return {
value: item.userId,
label: item.nickName
}
})
membersOptions.value = response.rows.map(item => {
return {
value: item.userId,
label: item.nickName
}
})
})
}
// 定义项目ID
let projectId = null;
function getProjectManage(){
projectId = proxy.$route.query.id;
getProject(projectId).then(response => {
form.value = response.data;
})
}
// 返回项目管理页面
const reset = () => {
// 返回项目
proxy.$router.push({ path: '/project' })
}
// 在组件挂载时执行
onMounted(() => {
getProjectManage()
getUserList()
});
</script>
<style scoped lang="scss">
</style>
<template>
<div class="form-container">
<!-- 标题和分割线 -->
<div class="header-wrapper">
<h3 class="input-label">物品基础信息</h3>
<div class="sep-wrapper">
<div class="sep-label"></div>
<div class="sep-bg"></div>
</div>
</div>
<el-form :model="form" label-width="80px">
<!-- 物品编号 -->
<el-row>
<el-col :span="24">
<label class="input-label">物品编号</label>
<el-input v-model="form.itemCode" disabled style="width: 20%;"></el-input>
</el-col>
</el-row>
<!-- 物品名称 -->
<el-row>
<el-col :span="24">
<label class="input-label">物品名称</label>
<el-input v-model="form.itemName" placeholder="请输入物品名称" style="width: 20%;"></el-input>
</el-col>
</el-row>
<!-- 物品类型 -->
<el-row>
<el-col :span="24">
<label class="input-label">物品类型</label>
<el-select v-model="form.itemType" filterable placeholder="请选择或输入" style="width: 20%;">
<el-option v-for="item in itemTypes" :key="item" :label="item" :value="item"></el-option>
</el-select>
</el-col>
</el-row>
<!-- 单位 -->
<el-row>
<el-col :span="24">
<label class="input-label">单位</label>
<el-input v-model="form.unit" placeholder="请输入单位" style="width: 20%;"></el-input>
</el-col>
</el-row>
</el-form>
<!-- 提交和保存草稿按钮 -->
<div class="button-container">
<el-button type="primary" @click="handleSubmit" style="margin-right: 20px;">提交</el-button>
<el-button @click="saveDraft">保存草稿</el-button>
</div>
</div>
</template>
<script>
import { addMaterial } from '@/api/system/material/material';
import { ElMessage } from 'element-plus';
export default {
data() {
return {
form: {
itemCode: '',
itemName: '',
itemType: '',
unit: ''
},
itemTypes: ['办公家具', '办公设备', '日杂百货']
};
},
methods: {
generateItemCode() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
return `WP${year}${month}${day}${hours}${minutes}${seconds}`;
},
handleSubmit() {
if (this.form.itemName && this.form.itemType && this.form.unit) {
addMaterial(this.form).then(response => {
ElMessage.success('物品信息提交成功');
// 清空表单
this.resetForm();
}).catch(error => {
ElMessage.error('物品信息提交失败: ' + error.message);
});
} else {
ElMessage.warning('请填写所有必填项');
}
},
saveDraft() {
// 保存草稿到本地存储
localStorage.setItem('materialDraft', JSON.stringify(this.form));
ElMessage.info('草稿已保存');
},
resetForm() {
this.form = {
itemCode: this.generateItemCode(), // 重新生成新的物品编号
itemName: '',
itemType: '',
unit: ''
};
// 清除草稿
localStorage.removeItem('materialDraft');
}
},
created() {
// 加载草稿
const draft = localStorage.getItem('materialDraft');
if (draft) {
this.form = JSON.parse(draft);
ElMessage.info('已加载草稿');
}
},
mounted() {
// 页面加载时生成物品编号
if (!this.form.itemCode) {
this.form.itemCode = this.generateItemCode();
}
}
};
</script>
<style scoped>
/* 样式部分保持不变 */
.form-container {
padding-left: 40px;
}
.input-label {
display: block;
font-weight: bold;
margin-bottom: 10px;
}
.sep-label {
border-radius: 0 8px;
width: 110px;
height: 12px;
overflow: hidden;
position: relative;
background-color: rgb(0, 137, 127);
}
.sep-bg {
width: 90%;
border-bottom: 4px solid;
border-color: rgb(0, 137, 127);
height: 2px;
opacity: .2;
margin-top: 6px;
}
.sep-wrapper {
display: flex;
align-items: center;
}
.header-wrapper {
margin-bottom: 20px;
}
.el-row + .el-row {
margin-top: 10px;
}
.button-container {
text-align: left;
margin-top: 20px;
}
</style>
This diff is collapsed.
<template>
<div class="form-container">
<!-- 标题和分割线 -->
<div class="header-wrapper">
<h3 class="input-label">入库信息填写</h3>
<div class="sep-wrapper">
<div class="sep-label"></div>
<div class="sep-bg"></div>
</div>
</div>
<el-form :model="form" label-width="80px">
<!-- 入库日期 -->
<el-row :gutter="20">
<el-col :span="12">
<label class="input-label">入库日期</label>
<el-date-picker v-model="form.entryDate" type="date" placeholder="选择日期" style="width: 90%;"></el-date-picker>
</el-col>
<!-- 入库人员 -->
<el-col :span="12">
<label class="input-label">入库人员</label>
<el-input v-model="form.entryPerson" prefix-icon="el-icon-user" placeholder="请输入入库人员" style="width: 90%;"></el-input>
</el-col>
</el-row>
<!-- 物品类型 -->
<el-row :gutter="20">
<el-col :span="12">
<label class="input-label">物品类型</label>
<el-select v-model="form.itemType" filterable placeholder="请选择或输入" style="width: 90%;" @change="onItemTypeChange">
<el-option v-for="item in itemTypes" :key="item" :label="item" :value="item"></el-option>
</el-select>
</el-col>
<!-- 物品名称 -->
<el-col :span="12">
<label class="input-label">物品名称</label>
<el-select v-model="form.itemName" filterable placeholder="请选择或输入" style="width: 90%;">
<el-option v-for="item in itemNames" :key="item" :label="item" :value="item"></el-option>
</el-select>
</el-col>
</el-row>
<!-- 单位和数量 -->
<el-row :gutter="20">
<el-col :span="12">
<label class="input-label">单位</label>
<el-input v-model="form.unit" placeholder="请输入单位" style="width: 90%;"></el-input>
</el-col>
<el-col :span="12">
<label class="input-label">数量</label>
<el-input-number v-model="form.entryQuantity" :min="1" style="width: 90%;"></el-input-number>
</el-col>
</el-row>
<!-- 入库方式 -->
<el-row>
<el-col :span="24">
<label class="input-label">入库方式</label>
<el-radio-group v-model="form.entryMethod" style="display: block; margin-bottom: 20px;">
<el-radio label="采购入库" class="item">采购入库</el-radio><br>
<el-radio label="盘点入库">盘点入库</el-radio>
</el-radio-group>
</el-col>
</el-row>
<!-- 标题和分割线 -->
<div class="header-wrapper">
<h3 class="input-label">入库审批</h3>
<div class="sep-wrapper">
<div class="sep-label"></div>
<div class="sep-bg"></div>
</div>
</div>
<!-- 审批时间 -->
<el-row>
<el-col :span="12">
<label class="input-label">审批时间</label>
<el-date-picker v-model="form.approvalDate" type="date" placeholder="选择日期" style="width: 90%;"></el-date-picker>
</el-col>
<el-col :span="12">
<label class="input-label">是否入库合格</label>
<el-radio-group v-model="form.isQualified" style="display: block; margin-bottom: 20px;">
<el-radio label="合格" class="item">合格</el-radio><br>
<el-radio label="不合格">不合格</el-radio>
</el-radio-group>
</el-col>
</el-row>
</el-form>
<!-- 提交和保存草稿按钮 -->
<div class="button-container">
<el-button type="primary" @click="submitForm" style="margin-right: 20px;">提交</el-button>
<el-button @click="saveDraft">保存草稿</el-button>
</div>
</div>
</template>
<script>
import { ElMessageBox } from 'element-plus';
import { addEntry } from '@/api/system/material/entry';
import { listMaterial } from '@/api/system/material/material';
export default {
data() {
return {
form: {
entryDate: '',
entryPerson: '',
itemType: '',
itemName: '',
unit: '',
entryQuantity: 1,
entryMethod: '采购入库',
approvalDate: '',
isQualified: '合格'
},
itemTypes: ['办公家具', '办公设备', '日杂百货'],
itemNames: [],
materials: []
};
},
methods: {
submitForm() {
try {
addEntry(this.form).then(response => {
ElMessageBox.alert('提交成功', '提示', {
confirmButtonText: '确定',
callback: action => {
// 提交成功后清空草稿
localStorage.removeItem('materialApplyDraft');
this.$message.info('草稿已清空');
// 重置表单
this.resetForm();
}
});
}).catch(error => {
ElMessageBox.alert('提交失败', '提示', {
confirmButtonText: '确定',
callback: action => {}
});
});
} catch (error) {
ElMessageBox.alert('提交失败', '提示', {
confirmButtonText: '确定',
callback: action => {}
});
}
},
resetForm() {
this.form = {
entryDate: '',
entryPerson: '',
itemType: '',
itemName: '',
unit: '',
entryQuantity: 1,
entryMethod: '采购入库',
approvalDate: '',
isQualified: '合格'
};
this.itemNames = [];
},
saveDraft() {
// 保存草稿到本地存储
localStorage.setItem('materialApplyDraft', JSON.stringify(this.form));
this.$message.info('草稿已保存');
},
fetchMaterials() {
listMaterial().then(response => {
console.log('Response:', response); // 添加调试信息
if (response && response.code === 200) {
if (Array.isArray(response.rows)) { // 直接检查 response.rows
this.materials = response.rows; // 确保正确赋值
this.updateItemNames(); // 确保在材料加载后更新物品名称
} else {
this.$message.error('获取物品信息失败: 返回数据格式不正确');
}
} else {
this.$message.error('获取物品信息失败: ' + response.msg);
}
}).catch(error => {
this.$message.error('获取物品信息失败: ' + error.message);
});
},
updateItemNames() {
if (this.form.itemType) {
this.itemNames = this.materials
.filter(material => material.itemType === this.form.itemType)
.map(material => material.itemName);
} else {
this.itemNames = [];
}
},
onItemTypeChange(newItemType) {
this.form.itemType = newItemType;
this.form.itemName = ''; // 清空物品名称
this.form.unit = ''; // 清空单位
this.updateItemNames(); // 更新物品名称选项
},
updateUnitBasedOnItemName() {
const selectedItem = this.materials.find(material =>
material.itemType === this.form.itemType &&
material.itemName === this.form.itemName
);
if (selectedItem) {
this.form.unit = selectedItem.unit;
} else {
this.form.unit = '';
}
}
},
watch: {
'form.itemType': {
handler(newItemType) {
this.form.itemName = ''; // 清空物品名称
this.form.unit = ''; // 清空单位
this.updateItemNames();
},
immediate: true
},
'form.itemName': {
handler(newItemName) {
this.updateUnitBasedOnItemName();
},
immediate: true
}
},
created() {
// 加载草稿
const draft = localStorage.getItem('materialApplyDraft');
if (draft) {
this.form = JSON.parse(draft);
this.$message.info('已加载草稿');
this.resetForm();
}
// 获取物品信息
this.fetchMaterials();
}
};
</script>
<style scoped>
.form-container {
padding-left: 40px;
}
.input-label {
display: block;
font-weight: bold;
margin-bottom: 10px;
}
/* 分割线样式 */
.sep-label {
border-radius: 0 8px;
width: 110px;
height: 12px;
overflow: hidden;
position: relative;
background-color: rgb(0, 137, 127);
}
.sep-bg {
width: 90%;
border-bottom: 4px solid;
border-color: rgb(0, 137, 127);
height: 2px;
opacity: .2;
margin-top: 6px; /* 调整此值以适应布局 */
}
.sep-wrapper {
display: flex;
align-items: center; /* 垂直居中 */
}
.header-wrapper {
margin-bottom: 20px;
}
/* 增加行间距 */
.el-row + .el-row {
margin-top: 10px;
}
.item {
margin-bottom: 10px; /* 设置你想要的间隔大小 */
}
.button-container {
text-align: left; /* 左对齐按钮 */
margin-top: 20px; /* 确保有足够的顶部间距 */
}
</style>
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment