feat: 完整功能迭代 — 移动端+PC端全面优化
新增: - 今日纪要 (6分类+彩色标签+时间选择器) - 客户经理PC端工作台 (我的数据,5模块CRUD) - 用户管理页 (支局长修改角色) - 客户备注/收支费用(金额+单位)/联系人管理 - 拜访人姓名+电话字段 - 客户导入导出/旧周报导入模板下载 - 序号列+分页(25/50/100) 修复/优化: - Hash路由→HTML5 History, Casdoor回调正常 - 时区统一为Asia/Shanghai (today_cst) - 数据库懒加载→selectinload预加载 - 日期解析兼容ISO datetime字符串 - 文件上传定位修复 (position:relative) - 表单button type='button'防止误提交 - 分管领导权限(只读客户档案,不可编辑) - 侧边栏折叠+SVG图标 - 拜访方式/紧急度统一chip风格 - 时间范围统一为el-time-picker(is-range) - 全局CSS设计变量+box-sizing修复滚动条 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -13,8 +13,10 @@ const miniBusiness = ref<any[]>([])
|
||||
const dailyNotes = ref<any[]>([])
|
||||
const keyVisits = ref<any[]>([])
|
||||
const customers = ref<any[]>([])
|
||||
const allUsers = ref<any[]>([])
|
||||
const plannedVisitors = ref<string[]>([])
|
||||
const dialogTimeRange = ref<any>(null)
|
||||
|
||||
// Dialog
|
||||
const dialogVisible = ref(false)
|
||||
const dialogMode = ref<'create' | 'edit'>('create')
|
||||
const dialogType = ref('')
|
||||
@@ -22,10 +24,23 @@ const form = ref<any>({})
|
||||
|
||||
const categories = ['行政事务', '合同整理', '发票处理', '内部会议', '培训学习', '其他']
|
||||
|
||||
const statusPick = ref<Record<string, string>>({})
|
||||
|
||||
const planStatuses = ['计划中', '已完成', '已取消']
|
||||
const miniStatuses = ['跟进中', '已签约', '已流失']
|
||||
const keyStatuses = ['未开始', '进行中', '已完成']
|
||||
|
||||
onMounted(async () => {
|
||||
await Promise.all([loadAll(), loadCustomers()])
|
||||
await Promise.all([loadAll(), loadCustomers(), loadUsers()])
|
||||
})
|
||||
|
||||
async function loadUsers() {
|
||||
try {
|
||||
const res = await api.get('/users/')
|
||||
allUsers.value = res.data || []
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
function typeLabel(t: string) {
|
||||
const labels: Record<string, string> = { visit: '拜访记录', note: '今日纪要', plan: '工作计划', mini: '小微商机', key: '要客拜访' }
|
||||
return labels[t] || ''
|
||||
@@ -57,23 +72,31 @@ async function loadAll() {
|
||||
|
||||
function openCreate(type: string) {
|
||||
dialogMode.value = 'create'; dialogType.value = type
|
||||
if (type === 'visit') form.value = { customer_id: '', visit_date: todayStr(), visit_method: '上门', time_range: '', communication_content: '', customer_demand: '' }
|
||||
dialogTimeRange.value = null
|
||||
if (type === 'visit') form.value = { customer_id: '', visit_date: todayStr(), visit_method: '上门', time_range: '', visitor_name: '', visitor_phone: '', communication_content: '', customer_demand: '' }
|
||||
else if (type === 'note') form.value = { note_date: todayStr(), category: '其他', content: '', time_range: '' }
|
||||
else if (type === 'plan') form.value = { customer_id: '', plan_content: '', plan_date: todayStr(), status: '计划中' }
|
||||
else if (type === 'mini') form.value = { customer_id: '', product_type: '', amount: '', follow_up_detail: '', status: '跟进中', expected_revenue_date: '' }
|
||||
else if (type === 'key') form.value = { customer_id: '', urgency_level: '一般', description: '', progress_status: '未开始', planned_date: '', planned_visitor: '', visit_target: '' }
|
||||
else if (type === 'key') { form.value = { customer_id: '', urgency_level: '一般', description: '', progress_status: '未开始', planned_date: '', planned_visitor: '', visit_target: '' }; plannedVisitors.value = [] }
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
function openEdit(type: string, item: any) {
|
||||
dialogMode.value = 'edit'; dialogType.value = type
|
||||
form.value = { ...item }
|
||||
dialogTimeRange.value = null
|
||||
if ((type === 'visit' || type === 'note') && item.time_range && item.time_range.includes('-')) {
|
||||
const parts = item.time_range.split('-')
|
||||
dialogTimeRange.value = [parts[0], parts[1]]
|
||||
}
|
||||
if (type === 'key') {
|
||||
plannedVisitors.value = item.planned_visitor ? item.planned_visitor.split('、') : []
|
||||
}
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
async function handleSave() {
|
||||
const t = dialogType.value
|
||||
const d = form.value
|
||||
const t = dialogType.value; const d = form.value
|
||||
try {
|
||||
if (dialogMode.value === 'create') {
|
||||
switch (t) {
|
||||
@@ -113,6 +136,36 @@ async function handleDelete(type: string, id: string) {
|
||||
} catch (e: any) { if (e !== 'cancel') ElMessage.error('删除失败') }
|
||||
}
|
||||
|
||||
function onVisitorsChange(val: string[]) {
|
||||
form.value.planned_visitor = val.join('、')
|
||||
}
|
||||
|
||||
function onDialogTimeChange(val: [string, string] | null) {
|
||||
form.value.time_range = val ? val.join('-') : ''
|
||||
}
|
||||
|
||||
// Quick status change
|
||||
async function quickStatusChange(type: string, row: any, newStatus: string) {
|
||||
try {
|
||||
await ElMessageBox.confirm(`确定将状态改为「${newStatus}」?`, '确认', { type: 'warning', confirmButtonText: '确定', cancelButtonText: '取消' })
|
||||
const payload: any = {}
|
||||
if (type === 'plan') payload.status = newStatus
|
||||
else if (type === 'mini') payload.status = newStatus
|
||||
else if (type === 'key') payload.progress_status = newStatus
|
||||
let url = ''
|
||||
if (type === 'plan') url = `/work-plans/${row.id}`
|
||||
else if (type === 'mini') url = `/mini-business/${row.id}`
|
||||
else if (type === 'key') url = `/key-visits/${row.id}`
|
||||
await api.put(url, payload)
|
||||
ElMessage.success('状态已更新')
|
||||
await loadAll()
|
||||
} catch (e: any) {
|
||||
if (e !== 'cancel') ElMessage.error('更新失败: ' + (e.response?.data?.detail || e.message))
|
||||
// Reset statusPick back to original on cancel/error
|
||||
delete statusPick.value[row.id]
|
||||
}
|
||||
}
|
||||
|
||||
const visitsByDate = computed(() => {
|
||||
const g: Record<string, any[]> = {}
|
||||
for (const v of visits.value) { const d = v.visit_date; if (!g[d]) g[d] = []; g[d].push(v) }
|
||||
@@ -127,24 +180,32 @@ const notesByDate = computed(() => {
|
||||
|
||||
<template>
|
||||
<div class="workspace" v-loading="loading">
|
||||
<h3>我的工作数据</h3>
|
||||
<div class="page-head">
|
||||
<h2 class="page-title">我的工作数据</h2>
|
||||
<div class="page-rule"></div>
|
||||
</div>
|
||||
|
||||
<el-card>
|
||||
<el-tabs v-model="activeTab">
|
||||
<!-- 拜访记录 -->
|
||||
<!-- ═══ 拜访记录 ═══ -->
|
||||
<el-tab-pane label="拜访记录" name="visits">
|
||||
<div style="margin-bottom:12px"><el-button type="primary" size="small" @click="openCreate('visit')">+ 新建拜访</el-button></div>
|
||||
<div v-for="[date, items] in visitsByDate" :key="date" class="date-group">
|
||||
<h4>📅 {{ date }}</h4>
|
||||
<h4 class="date-title">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:4px; color: var(--gold)">
|
||||
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line>
|
||||
</svg>
|
||||
{{ date }}
|
||||
</h4>
|
||||
<el-table :data="items" stripe size="small">
|
||||
<el-table-column prop="customer_name" label="客户" width="130">
|
||||
<template #default="{ row }"><el-link type="primary" :underline="false">{{ row.customer_name }}</el-link></template>
|
||||
<template #default="{ row }"><el-link type="primary" :underline="false" @click="openEdit('visit', row)">{{ row.customer_name }}</el-link></template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="visit_method" label="方式" width="60" />
|
||||
<el-table-column prop="time_range" label="时间" width="100" />
|
||||
<el-table-column prop="communication_content" label="沟通内容" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="120">
|
||||
<el-table-column label="操作" width="70">
|
||||
<template #default="{ row }">
|
||||
<el-button text size="small" @click="openEdit('visit', row)">编辑</el-button>
|
||||
<el-button text size="small" type="danger" @click="handleDelete('visit', row.id)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -153,18 +214,24 @@ const notesByDate = computed(() => {
|
||||
<div v-if="!visits.length" class="empty">暂无数据</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 今日纪要 -->
|
||||
<!-- ═══ 今日纪要 ═══ -->
|
||||
<el-tab-pane label="今日纪要" name="daily_notes">
|
||||
<div style="margin-bottom:12px"><el-button type="primary" size="small" @click="openCreate('note')">+ 新建纪要</el-button></div>
|
||||
<div v-for="[date, items] in notesByDate" :key="date" class="date-group">
|
||||
<h4>📅 {{ date }}</h4>
|
||||
<h4 class="date-title">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="margin-right:4px; color: var(--gold)">
|
||||
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line>
|
||||
</svg>
|
||||
{{ date }}
|
||||
</h4>
|
||||
<el-table :data="items" stripe size="small">
|
||||
<el-table-column prop="category" label="分类" width="100"><template #default="{ row }"><el-tag size="small">{{ row.category }}</el-tag></template></el-table-column>
|
||||
<el-table-column prop="content" label="工作内容" min-width="250" show-overflow-tooltip />
|
||||
<el-table-column prop="content" label="工作内容" min-width="250" show-overflow-tooltip>
|
||||
<template #default="{ row }"><el-link type="primary" :underline="false" @click="openEdit('note', row)">{{ row.content }}</el-link></template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="time_range" label="时间" width="100" />
|
||||
<el-table-column label="操作" width="120">
|
||||
<el-table-column label="操作" width="70">
|
||||
<template #default="{ row }">
|
||||
<el-button text size="small" @click="openEdit('note', row)">编辑</el-button>
|
||||
<el-button text size="small" type="danger" @click="handleDelete('note', row.id)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -173,19 +240,31 @@ const notesByDate = computed(() => {
|
||||
<div v-if="!dailyNotes.length" class="empty">暂无数据</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 工作计划 -->
|
||||
<!-- ═══ 工作计划 ═══ -->
|
||||
<el-tab-pane label="工作计划" name="work_plans">
|
||||
<div style="margin-bottom:12px"><el-button type="primary" size="small" @click="openCreate('plan')">+ 新建计划</el-button></div>
|
||||
<el-table :data="workPlans" stripe size="small">
|
||||
<el-table-column prop="customer_name" label="客户" width="130">
|
||||
<template #default="{ row }"><el-link type="primary" :underline="false">{{ row.customer_name }}</el-link></template>
|
||||
<template #default="{ row }"><el-link type="primary" :underline="false" @click="openEdit('plan', row)">{{ row.customer_name }}</el-link></template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="plan_content" label="工作计划" min-width="250" show-overflow-tooltip />
|
||||
<el-table-column prop="plan_content" label="工作计划" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="plan_date" label="计划时间" width="110" />
|
||||
<el-table-column prop="status" label="状态" width="90"><template #default="{ row }"><el-tag size="small">{{ row.status }}</el-tag></template></el-table-column>
|
||||
<el-table-column label="操作" width="120">
|
||||
<el-table-column label="状态" width="120">
|
||||
<template #default="{ row }">
|
||||
<el-select
|
||||
v-model="statusPick[row.id]"
|
||||
size="small"
|
||||
style="width:100%"
|
||||
:placeholder="row.status"
|
||||
@change="(v: string) => quickStatusChange('plan', row, v)"
|
||||
@visible-change="(v: boolean) => { if (v) statusPick[row.id] = row.status }"
|
||||
>
|
||||
<el-option v-for="s in planStatuses" :key="s" :label="s" :value="s" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="70">
|
||||
<template #default="{ row }">
|
||||
<el-button text size="small" @click="openEdit('plan', row)">编辑</el-button>
|
||||
<el-button text size="small" type="danger" @click="handleDelete('plan', row.id)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -193,21 +272,33 @@ const notesByDate = computed(() => {
|
||||
<div v-if="!workPlans.length" class="empty">暂无数据</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 小微商机 -->
|
||||
<!-- ═══ 小微商机 ═══ -->
|
||||
<el-tab-pane label="小微商机" name="mini_biz">
|
||||
<div style="margin-bottom:12px"><el-button type="primary" size="small" @click="openCreate('mini')">+ 新建商机</el-button></div>
|
||||
<el-table :data="miniBusiness" stripe size="small">
|
||||
<el-table-column prop="customer_name" label="客户" width="130">
|
||||
<template #default="{ row }"><el-link type="primary" :underline="false">{{ row.customer_name }}</el-link></template>
|
||||
<template #default="{ row }"><el-link type="primary" :underline="false" @click="openEdit('mini', row)">{{ row.customer_name }}</el-link></template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="product_type" label="产品类型" width="120" />
|
||||
<el-table-column prop="amount" label="金额" width="90" />
|
||||
<el-table-column prop="follow_up_detail" label="跟进内容" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" width="90"><template #default="{ row }"><el-tag size="small">{{ row.status }}</el-tag></template></el-table-column>
|
||||
<el-table-column prop="expected_revenue_date" label="预计列收" width="110" />
|
||||
<el-table-column label="操作" width="120">
|
||||
<el-table-column label="状态" width="120">
|
||||
<template #default="{ row }">
|
||||
<el-select
|
||||
v-model="statusPick[row.id]"
|
||||
size="small"
|
||||
style="width:100%"
|
||||
:placeholder="row.status"
|
||||
@change="(v: string) => quickStatusChange('mini', row, v)"
|
||||
@visible-change="(v: boolean) => { if (v) statusPick[row.id] = row.status }"
|
||||
>
|
||||
<el-option v-for="s in miniStatuses" :key="s" :label="s" :value="s" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="expected_revenue_date" label="预计列收" width="110" />
|
||||
<el-table-column label="操作" width="70">
|
||||
<template #default="{ row }">
|
||||
<el-button text size="small" @click="openEdit('mini', row)">编辑</el-button>
|
||||
<el-button text size="small" type="danger" @click="handleDelete('mini', row.id)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -215,22 +306,34 @@ const notesByDate = computed(() => {
|
||||
<div v-if="!miniBusiness.length" class="empty">暂无数据</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 要客拜访 -->
|
||||
<!-- ═══ 要客拜访 ═══ -->
|
||||
<el-tab-pane label="要客拜访" name="key_visits">
|
||||
<div style="margin-bottom:12px"><el-button type="primary" size="small" @click="openCreate('key')">+ 新建要客拜访</el-button></div>
|
||||
<el-table :data="keyVisits" stripe size="small">
|
||||
<el-table-column prop="customer_name" label="客户" width="130">
|
||||
<template #default="{ row }"><el-link type="primary" :underline="false">{{ row.customer_name }}</el-link></template>
|
||||
<template #default="{ row }"><el-link type="primary" :underline="false" @click="openEdit('key', row)">{{ row.customer_name }}</el-link></template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="urgency_level" label="重要度" width="80"><template #default="{ row }"><el-tag size="small" :type="row.urgency_level==='紧急'?'danger':row.urgency_level==='重要'?'warning':''">{{ row.urgency_level }}</el-tag></template></el-table-column>
|
||||
<el-table-column prop="description" label="描述" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="progress_status" label="进展" width="80" />
|
||||
<el-table-column label="进展" width="120">
|
||||
<template #default="{ row }">
|
||||
<el-select
|
||||
v-model="statusPick[row.id]"
|
||||
size="small"
|
||||
style="width:100%"
|
||||
:placeholder="row.progress_status"
|
||||
@change="(v: string) => quickStatusChange('key', row, v)"
|
||||
@visible-change="(v: boolean) => { if (v) statusPick[row.id] = row.progress_status }"
|
||||
>
|
||||
<el-option v-for="s in keyStatuses" :key="s" :label="s" :value="s" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="planned_date" label="计划时间" width="110" />
|
||||
<el-table-column prop="planned_visitor" label="拜访人" width="80" />
|
||||
<el-table-column prop="visit_target" label="拜访对象" width="100" />
|
||||
<el-table-column label="操作" width="120">
|
||||
<el-table-column label="操作" width="70">
|
||||
<template #default="{ row }">
|
||||
<el-button text size="small" @click="openEdit('key', row)">编辑</el-button>
|
||||
<el-button text size="small" type="danger" @click="handleDelete('key', row.id)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -241,65 +344,62 @@ const notesByDate = computed(() => {
|
||||
</el-card>
|
||||
|
||||
<!-- Create/Edit Dialog -->
|
||||
<el-dialog v-model="dialogVisible" :title="(dialogMode === 'create' ? '新建' : '编辑') + typeLabel(dialogType)" width="520px">
|
||||
<el-dialog v-model="dialogVisible" :title="(dialogMode === 'create' ? '新建' : '编辑') + ' ' + typeLabel(dialogType)" width="520px">
|
||||
<el-form label-position="top" v-if="form">
|
||||
<!-- Customer selector for types that need it -->
|
||||
<el-form-item v-if="['visit','plan','mini','key'].includes(dialogType)" label="客户单位">
|
||||
<el-select v-model="form.customer_id" filterable remote :remote-method="(q: string) => loadCustomers(q)" placeholder="搜索选择客户" style="width:100%">
|
||||
<el-option v-for="c in customers" :key="c.id" :label="c.name" :value="c.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- Date -->
|
||||
<el-form-item v-if="dialogType === 'visit'" label="日期">
|
||||
<el-date-picker v-model="form.visit_date" type="date" style="width:100%" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="dialogType === 'note'" label="日期">
|
||||
<el-date-picker v-model="form.note_date" type="date" style="width:100%" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="dialogType === 'plan'" label="计划拜访时间">
|
||||
<el-date-picker v-model="form.plan_date" type="date" style="width:100%" />
|
||||
</el-form-item>
|
||||
<!-- Visit specific -->
|
||||
<el-form-item v-if="dialogType === 'visit'" label="日期"><el-date-picker v-model="form.visit_date" type="date" style="width:100%" /></el-form-item>
|
||||
<el-form-item v-if="dialogType === 'note'" label="日期"><el-date-picker v-model="form.note_date" type="date" style="width:100%" /></el-form-item>
|
||||
<el-form-item v-if="dialogType === 'plan'" label="计划拜访时间"><el-date-picker v-model="form.plan_date" type="date" style="width:100%" /></el-form-item>
|
||||
<template v-if="dialogType === 'visit'">
|
||||
<el-form-item label="拜访方式">
|
||||
<el-radio-group v-model="form.visit_method">
|
||||
<el-radio-button value="上门">上门</el-radio-button><el-radio-button value="电话">电话</el-radio-button><el-radio-button value="微信">微信</el-radio-button><el-radio-button value="出差">出差</el-radio-button>
|
||||
</el-radio-group>
|
||||
<div class="method-grid">
|
||||
<el-button v-for="m in ['上门','电话','微信','出差']" :key="m" size="small" :type="form.visit_method===m?'primary':''" @click="form.visit_method=m">{{ m }}</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="时间范围"><el-input v-model="form.time_range" /></el-form-item>
|
||||
<el-form-item label="时间范围">
|
||||
<el-time-picker v-model="dialogTimeRange" is-range format="HH:mm" value-format="HH:mm" range-separator="至" start-placeholder="开始" end-placeholder="结束" style="width:100%" @change="onDialogTimeChange" />
|
||||
</el-form-item>
|
||||
<el-form-item label="拜访人姓名"><el-input v-model="form.visitor_name" placeholder="实际拜访人姓名" /></el-form-item>
|
||||
<el-form-item label="拜访人电话"><el-input v-model="form.visitor_phone" placeholder="联系电话(可选)" /></el-form-item>
|
||||
<el-form-item label="沟通内容"><el-input v-model="form.communication_content" type="textarea" :rows="3" /></el-form-item>
|
||||
<el-form-item label="客户需求"><el-input v-model="form.customer_demand" type="textarea" :rows="2" /></el-form-item>
|
||||
</template>
|
||||
<!-- Note specific -->
|
||||
<template v-if="dialogType === 'note'">
|
||||
<el-form-item label="分类">
|
||||
<div style="display:flex;flex-wrap:wrap;gap:6px">
|
||||
<el-button v-for="c in categories" :key="c" :type="form.category===c?'primary':''" size="small" @click="form.category=c">{{ c }}</el-button>
|
||||
</div>
|
||||
<el-form-item label="分类"><div style="display:flex;flex-wrap:wrap;gap:6px"><el-button v-for="c in categories" :key="c" :type="form.category===c?'primary':''" size="small" @click="form.category=c">{{ c }}</el-button></div></el-form-item>
|
||||
<el-form-item label="时间范围">
|
||||
<el-time-picker v-model="dialogTimeRange" is-range format="HH:mm" value-format="HH:mm" range-separator="至" start-placeholder="开始" end-placeholder="结束" style="width:100%" @change="onDialogTimeChange" />
|
||||
</el-form-item>
|
||||
<el-form-item label="时间范围"><el-input v-model="form.time_range" /></el-form-item>
|
||||
<el-form-item label="工作内容"><el-input v-model="form.content" type="textarea" :rows="4" /></el-form-item>
|
||||
</template>
|
||||
<!-- Plan specific -->
|
||||
<template v-if="dialogType === 'plan'">
|
||||
<el-form-item label="工作计划"><el-input v-model="form.plan_content" type="textarea" :rows="4" /></el-form-item>
|
||||
<el-form-item label="状态"><el-select v-model="form.status"><el-option label="计划中" value="计划中" /><el-option label="已完成" value="已完成" /><el-option label="已取消" value="已取消" /></el-select></el-form-item>
|
||||
</template>
|
||||
<!-- Mini biz specific -->
|
||||
<template v-if="dialogType === 'mini'">
|
||||
<el-form-item label="产品类型"><el-input v-model="form.product_type" /></el-form-item>
|
||||
<el-form-item label="金额"><el-input v-model="form.amount" /></el-form-item>
|
||||
<el-form-item label="跟进内容"><el-input v-model="form.follow_up_detail" type="textarea" :rows="4" /></el-form-item>
|
||||
<el-form-item label="状态"><el-select v-model="form.status"><el-option label="跟进中" value="跟进中" /><el-option label="已签约" value="已签约" /><el-option label="已流失" value="已流失" /></el-select></el-form-item>
|
||||
<el-form-item label="预计列收时间"><el-input v-model="form.expected_revenue_date" /></el-form-item>
|
||||
<el-form-item label="预计列收时间"><el-date-picker v-model="form.expected_revenue_date" type="month" placeholder="选择月份" style="width:100%" value-format="YYYY-MM" /></el-form-item>
|
||||
</template>
|
||||
<!-- Key visit specific -->
|
||||
<template v-if="dialogType === 'key'">
|
||||
<el-form-item label="紧急重要度"><el-radio-group v-model="form.urgency_level"><el-radio-button value="一般">一般</el-radio-button><el-radio-button value="重要">重要</el-radio-button><el-radio-button value="紧急">紧急</el-radio-button></el-radio-group></el-form-item>
|
||||
<el-form-item label="紧急重要度">
|
||||
<div class="method-grid">
|
||||
<el-button v-for="u in ['一般','重要','紧急']" :key="u" size="small" :type="form.urgency_level===u ? (u==='紧急'?'danger':u==='重要'?'warning':'') : ''" @click="form.urgency_level=u">{{ u }}</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="内容描述"><el-input v-model="form.description" type="textarea" :rows="4" /></el-form-item>
|
||||
<el-form-item label="进展状态"><el-select v-model="form.progress_status"><el-option label="未开始" value="未开始" /><el-option label="进行中" value="进行中" /><el-option label="已完成" value="已完成" /></el-select></el-form-item>
|
||||
<el-form-item label="计划拜访时间"><el-input v-model="form.planned_date" /></el-form-item>
|
||||
<el-form-item label="计划拜访人"><el-input v-model="form.planned_visitor" /></el-form-item>
|
||||
<el-form-item label="计划拜访时间"><el-date-picker v-model="form.planned_date" type="date" placeholder="选择日期" style="width:100%" value-format="YYYY-MM-DD" /></el-form-item>
|
||||
<el-form-item label="计划拜访人(可多选)">
|
||||
<el-select v-model="plannedVisitors" multiple filterable allow-create default-first-option placeholder="选择或输入姓名(可多选)" style="width:100%" @change="onVisitorsChange">
|
||||
<el-option v-for="u in allUsers" :key="u.id" :label="u.name + (u.role==='director'?' (支局长)':u.role==='leader'?' (分管领导)':'')" :value="u.name" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="拜访对象"><el-input v-model="form.visit_target" /></el-form-item>
|
||||
</template>
|
||||
</el-form>
|
||||
@@ -312,8 +412,10 @@ const notesByDate = computed(() => {
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.workspace h3 { margin: 0 0 16px; }
|
||||
.page-head { margin-bottom: 20px; }
|
||||
.page-title { margin: 0; font-family: 'ZCOOL XiaoWei', STSong, serif; font-size: 22px; font-weight: 400; color: var(--ink); letter-spacing: 0.06em; }
|
||||
.page-rule { width: 32px; height: 3px; background: var(--gold); margin-top: 12px; }
|
||||
.date-group { margin-bottom: 20px; }
|
||||
.date-group h4 { margin: 12px 0 8px; font-size: 14px; color: #303133; }
|
||||
.empty { text-align: center; color: #c0c4cc; padding: 40px 0; }
|
||||
.date-title { display: flex; align-items: center; margin: 12px 0 8px; font-family: 'ZCOOL XiaoWei', STSong, serif; font-size: 14px; color: var(--ink); letter-spacing: 0.04em; }
|
||||
.empty { text-align: center; color: var(--c-text-muted); padding: 40px 0; font-family: 'Noto Serif SC', STSong, serif; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user