批量更新功能
This commit is contained in:
1 parent
6f106e43af
commit
a26c98b92b
79 files changed
+4529
-724
No files matched your search
@@ -12,10 +12,27 @@
|
||||
<div class="toolbar-status">
|
||||
<el-tag :type="projectStatusTag(project.status)" size="small">{{ projectStatusText(project.status) }}</el-tag>
|
||||
<el-tag v-if="projectOverdue(project).overdue" type="danger" size="small" effect="dark">
|
||||
{{ overdueText(projectOverdue(project).days) }}
|
||||
{{ projectOverdue(project).text }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="toolbar-actions">
|
||||
<!-- 状态流转:与合同详情一致,右上角下拉切换项目状态 -->
|
||||
<el-dropdown trigger="click" @command="(cmd) => handleChangeStatus(cmd)">
|
||||
<el-button link type="warning" size="small">
|
||||
状态流转<el-icon style="margin-left: 2px"><ArrowDown /></el-icon>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item
|
||||
v-for="i in statusOptionsExcept(project.status)"
|
||||
:key="i.value"
|
||||
:command="i.value"
|
||||
>
|
||||
{{ i.label }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<el-button type="primary" size="small" :icon="Edit" @click="handleEdit">编辑</el-button>
|
||||
<el-button type="danger" size="small" :icon="Delete" @click="handleDelete">删除</el-button>
|
||||
</div>
|
||||
@@ -26,14 +43,9 @@
|
||||
<DetailBasic :project="project" />
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 联系人(正式客户通讯录) -->
|
||||
<!-- 联系人(按项目类型分组:从对应企业通讯录中挑选,支持多选) -->
|
||||
<el-tab-pane :label="`联系人 (${counts.contact})`" name="contact">
|
||||
<DetailContact
|
||||
ref="contactRef"
|
||||
:company-id="project.customer_id"
|
||||
company-type="customer"
|
||||
@count="counts.contact = $event"
|
||||
/>
|
||||
<DetailContact ref="contactRef" :project="project" @count="counts.contact = $event" />
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 跟进记录(链路累积:线索 + 商机 + 项目) -->
|
||||
@@ -55,6 +67,7 @@
|
||||
ref="contractRef"
|
||||
:project-id="project.id"
|
||||
:project-name="project.project_name || ''"
|
||||
:project-type="project.project_type"
|
||||
@count="counts.contract = $event"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
@@ -93,8 +106,8 @@
|
||||
<script setup>
|
||||
import { ref, reactive, watch } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { Edit, Delete } from "@element-plus/icons-vue";
|
||||
import { deleteProject } from "@/api/crmPipeline";
|
||||
import { Edit, Delete, ArrowDown } from "@element-plus/icons-vue";
|
||||
import { deleteProject, changeProjectStatus, getProjectDetail } from "@/api/crmPipeline";
|
||||
import DetailBasic from "./detail_basic.vue";
|
||||
import DetailContact from "./detail_contact.vue";
|
||||
import DetailFollow from "./detail_follow.vue";
|
||||
@@ -102,7 +115,12 @@ import DetailContract from "./detail_contract.vue";
|
||||
import DetailAttach from "./detail_attach.vue";
|
||||
import DetailDocs from "./detail_docs.vue";
|
||||
import DetailLog from "./detail_log.vue";
|
||||
import { projectStatusText, projectStatusTag, projectOverdue, overdueText } from "../../dict";
|
||||
import {
|
||||
PROJECT_STATUS_OPTIONS,
|
||||
projectStatusText,
|
||||
projectStatusTag,
|
||||
projectOverdue,
|
||||
} from "../../dict";
|
||||
|
||||
const props = defineProps({
|
||||
visible: { type: Boolean, default: false },
|
||||
@@ -145,6 +163,24 @@ function handleEdit() {
|
||||
emit("edit", props.project);
|
||||
}
|
||||
|
||||
/** 状态流转候选:排除当前状态 */
|
||||
function statusOptionsExcept(cur) {
|
||||
return PROJECT_STATUS_OPTIONS.filter((i) => String(i.value) !== String(cur));
|
||||
}
|
||||
|
||||
/** 项目状态流转:成功后更新本地展示并通知父组件刷新列表 */
|
||||
async function handleChangeStatus(status) {
|
||||
if (!props.project?.id) return;
|
||||
try {
|
||||
await changeProjectStatus(props.project.id, Number(status));
|
||||
ElMessage.success(`状态已更新为「${projectStatusText(status)}」`);
|
||||
props.project.status = Number(status);
|
||||
emit("refresh");
|
||||
} catch (e) {
|
||||
ElMessage.error(e.message || "状态更新失败");
|
||||
}
|
||||
}
|
||||
|
||||
async function handleDelete() {
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定删除项目「${props.project.project_name}」吗?删除后不可恢复。`, "删除确认", {
|
||||
@@ -160,8 +196,19 @@ async function handleDelete() {
|
||||
}
|
||||
|
||||
/** 抽屉打开后刷新各 Tab 数据 */
|
||||
function loadAll() {
|
||||
async function loadAll() {
|
||||
if (!props.project?.id) return;
|
||||
// 列表行数据是打开页面时的快照,联系人选中集合等字段可能已过期(如刚在其他项目/本次会话保存过),
|
||||
// 先拉取最新详情刷新快照,各 Tab(含联系人)再按最新数据加载
|
||||
try {
|
||||
const res = await getProjectDetail(props.project.id);
|
||||
const data = res?.data;
|
||||
if (data && typeof data === "object" && props.project) {
|
||||
Object.assign(props.project, data);
|
||||
}
|
||||
} catch (e) {
|
||||
// 详情接口失败时保持快照展示,不阻断其他 Tab
|
||||
}
|
||||
contactRef.value?.reload();
|
||||
followRef.value?.reload();
|
||||
contractRef.value?.reload();
|
||||
|
||||
Reference in new issue
Block a user