上传
This commit is contained in:
@@ -38,13 +38,15 @@
|
||||
<el-table-column prop="extraPayMoney" label="金额" />
|
||||
<el-table-column prop="remark" label="备注" />
|
||||
</el-table>
|
||||
<el-divider direction="horizontal" content-position="left">额外支出</el-divider>
|
||||
<el-table :data="extraPayList" border stripe>
|
||||
<el-table-column type="index" width="50" />
|
||||
<el-table-column prop="extraPayType" label="支出项" />
|
||||
<el-table-column prop="extraPayMoney" label="金额" />
|
||||
<el-table-column prop="remark" label="备注" />
|
||||
</el-table>
|
||||
<div v-if="checkPermi(['clue:order:add-fee'])">
|
||||
<el-divider direction="horizontal" content-position="left">额外支出</el-divider>
|
||||
<el-table :data="extraPayList" border stripe>
|
||||
<el-table-column type="index" width="50" />
|
||||
<el-table-column prop="extraPayType" label="支出项" />
|
||||
<el-table-column prop="extraPayMoney" label="金额" />
|
||||
<el-table-column prop="remark" label="备注" />
|
||||
</el-table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="回款记录" name="returnRecord">
|
||||
<el-table :data="returnRecordList" border stripe>
|
||||
@@ -78,6 +80,7 @@ import { getSimpleFieldList as getOrderFieldList } from '@/api/clue/orderField'
|
||||
import { getPaymentPage } from '@/api/clue/payment'
|
||||
import { getAfterSalePage } from '@/api/clue/afterSale'
|
||||
|
||||
import { checkPermi } from '@/utils/permission'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
|
||||
const tabName = ref('clueInfo')
|
||||
|
||||
@@ -24,10 +24,10 @@
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="followTime" label="下次跟进时间">
|
||||
<el-table-column prop="nextFollowTime" label="下次跟进时间">
|
||||
<template #default="{ row }">
|
||||
<el-date-picker
|
||||
v-model="row.followTime"
|
||||
v-model="row.nextFollowTime"
|
||||
type="date"
|
||||
placeholder="选择日期时间"
|
||||
:disabled="!row.editable"
|
||||
@@ -266,7 +266,7 @@ async function handleSave() {
|
||||
message.info('请将跟进人填写完整!')
|
||||
return
|
||||
}
|
||||
if (!address.value) {
|
||||
if (appStore.getAppInfo?.instanceType == 1 && !address.value) {
|
||||
message.info('请选择学员位置!')
|
||||
return
|
||||
}
|
||||
@@ -304,7 +304,7 @@ async function handleSave() {
|
||||
function handleAppendFollow() {
|
||||
followList.value.push({
|
||||
userId: undefined,
|
||||
followTime: formatDate(new Date()),
|
||||
nextFollowTime: formatDate(new Date()),
|
||||
editable: true
|
||||
})
|
||||
}
|
||||
|
||||
@@ -25,6 +25,18 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="意向状态" prop="intentionState">
|
||||
<el-select v-model="form.intentionState" filterable>
|
||||
<el-option
|
||||
v-for="item in intentionOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24" :offset="0">
|
||||
@@ -80,9 +92,12 @@
|
||||
<script setup name="DialogFollow">
|
||||
import { getSkillPage } from '@/api/clue/skill'
|
||||
import { createFollow } from '@/api/clue/followRecord'
|
||||
import { getDictOptions } from '@/utils/dict'
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
const intentionOptions = getDictOptions('intention_state')
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
@@ -97,18 +112,19 @@ const rules = {
|
||||
content: { required: true, message: '跟进内容不可为空', trigger: 'blur' }
|
||||
}
|
||||
|
||||
const open = async (clueId) => {
|
||||
const open = async (clueId, status) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = '新增跟进记录'
|
||||
resetForm(clueId)
|
||||
resetForm(clueId, status)
|
||||
}
|
||||
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
function resetForm(clueId) {
|
||||
function resetForm(clueId, status) {
|
||||
form.value = {
|
||||
clueId,
|
||||
operateTime: undefined,
|
||||
operateTime: formatDate(new Date(), 'YYYY-MM-DD HH:mm'),
|
||||
nextFollowTime: undefined,
|
||||
intentionState: status,
|
||||
content: undefined
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ const detail = ref('')
|
||||
function open(info) {
|
||||
title.value = `【${info.schoolName}】详细信息`
|
||||
show.value = true
|
||||
detail.value = info.schoolRemark || '该驾校暂未配置详细信息'
|
||||
detail.value = info.introduce || '该驾校暂未配置详细信息'
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<Dialog title="成交登记" v-model="show" width="820px">
|
||||
<Dialog title="成交登记" v-model="show" width="900px">
|
||||
<Descriptions
|
||||
:title="`线索信息-${info.name}`"
|
||||
:data="info"
|
||||
@@ -124,7 +124,9 @@
|
||||
</el-col>
|
||||
<!-- 进销存模式 -->
|
||||
<el-col :span="24" :offset="0" v-if="appStore.getAppInfo?.instanceType == 2">
|
||||
<el-divider direction="horizontal" content-position="left">成交产品</el-divider>
|
||||
<el-divider direction="horizontal" content-position="left">
|
||||
成交产品<span v-if="prodTotalPrice">,应收:{{ prodTotalPrice }}</span>
|
||||
</el-divider>
|
||||
<el-button
|
||||
class="mb-5px"
|
||||
type="primary"
|
||||
@@ -161,6 +163,11 @@
|
||||
placeholder="选择规格"
|
||||
filterable
|
||||
:disabled="!row.productId"
|
||||
@change="
|
||||
row.price = specsOptions(row.productId).find(
|
||||
(it) => it.specsId == row.specsId
|
||||
).price
|
||||
"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in specsOptions(row.productId)"
|
||||
@@ -171,6 +178,7 @@
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="price" label="销售单价" width="100px" />
|
||||
<el-table-column prop="signNum" label="成交数量" width="100px">
|
||||
<template #default="{ row }">
|
||||
<el-input-number
|
||||
@@ -199,7 +207,9 @@
|
||||
</el-table>
|
||||
</el-col>
|
||||
<el-col :span="24" :offset="0" class="mb-18px">
|
||||
<el-divider direction="horizontal" content-position="left">其他费用</el-divider>
|
||||
<el-divider direction="horizontal" content-position="left">
|
||||
其他费用<span v-if="extraTotalPrice">,应收:{{ extraTotalPrice }}</span>
|
||||
</el-divider>
|
||||
<el-button
|
||||
class="mb-5px"
|
||||
type="primary"
|
||||
@@ -247,6 +257,13 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-divider
|
||||
v-if="prodTotalPrice + extraTotalPrice"
|
||||
direction="horizontal"
|
||||
content-position="left"
|
||||
>
|
||||
合计应收:{{ prodTotalPrice + extraTotalPrice }}
|
||||
</el-divider>
|
||||
</el-col>
|
||||
<el-col :span="24" :offset="0">
|
||||
<el-form-item label="备注">
|
||||
@@ -302,6 +319,17 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const prodTotalPrice = computed(() => {
|
||||
return form.value.signProducts.reduce(
|
||||
(pre, cur) => pre + (cur?.price || 0) * (cur?.signNum || 0),
|
||||
0
|
||||
)
|
||||
})
|
||||
|
||||
const extraTotalPrice = computed(() => {
|
||||
return form.value.extraPay.reduce((pre, cur) => pre + cur.extraPayMoney, 0)
|
||||
})
|
||||
|
||||
const showSchema = computed(() => {
|
||||
const arr = [
|
||||
{
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
<el-tabs v-model="infoIndex" type="border-card">
|
||||
<el-tab-pane label="跟进记录" name="followRecord">
|
||||
<el-button
|
||||
v-if="followList.length"
|
||||
v-hasPermi="['clue:pool:update']"
|
||||
class="mb-10px"
|
||||
type="primary"
|
||||
@@ -139,7 +140,7 @@
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<!-- 新建编辑跟进信息 -->
|
||||
<DialogFollow ref="followRef" @success="getFollowList" />
|
||||
<DialogFollow ref="followRef" @success="followSuccess" />
|
||||
<DialogSchoolInfo ref="schoolInfoDialog" />
|
||||
</el-drawer>
|
||||
</template>
|
||||
@@ -252,6 +253,12 @@ async function open(id) {
|
||||
}
|
||||
}
|
||||
|
||||
function followSuccess() {
|
||||
ClueApi.getClue(id).then((data) => {
|
||||
info.value = { ...data, ...data.diyParams }
|
||||
})
|
||||
}
|
||||
|
||||
const placeList = ref([])
|
||||
async function getSchoolPlace() {
|
||||
const data = await getPlaceList()
|
||||
@@ -418,7 +425,7 @@ defineExpose({
|
||||
|
||||
const followRef = ref()
|
||||
function addFollow() {
|
||||
followRef.value.open(info.value.clueId)
|
||||
followRef.value.open(info.value.clueId, info.value.intentionState)
|
||||
}
|
||||
|
||||
function destroyMap() {
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
text
|
||||
style="padding: 0"
|
||||
@click="handleFollow(row)"
|
||||
v-if="queryType != 4"
|
||||
v-hasPermi="['clue:pool:update']"
|
||||
>
|
||||
快速新增
|
||||
@@ -109,7 +110,7 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
:disabled="scope.row.state == '已成交'"
|
||||
:disabled="scope.row.state == '成交'"
|
||||
@click="handleSuccess(scope.row)"
|
||||
v-hasPermi="['clue:pool:enroll']"
|
||||
>
|
||||
@@ -268,7 +269,7 @@ function handleDetail(row) {
|
||||
}
|
||||
|
||||
function handleFollow(row) {
|
||||
followRef.value.open(row.clueId)
|
||||
followRef.value.open(row.clueId, row.intentionState)
|
||||
}
|
||||
|
||||
async function makeCall(phone) {
|
||||
|
||||
@@ -387,14 +387,16 @@ function onSubmit() {
|
||||
const element = diyFieldList.value[i]
|
||||
data.diyParams[element.field] = data[element.field]
|
||||
}
|
||||
const id = route.query.id
|
||||
const id = route.query.id || form.value.productId
|
||||
if (!id) {
|
||||
await ProductApi.createProduct(data)
|
||||
const resp = await ProductApi.createProduct(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
form.value.productId = resp
|
||||
} else {
|
||||
await ProductApi.updateProduct(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
getDetail()
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
@@ -461,10 +463,11 @@ const formLoading = ref(false)
|
||||
|
||||
/** 获得详情 */
|
||||
const getDetail = async () => {
|
||||
if (route.query?.id) {
|
||||
const id = route.query?.id || form.value.productId
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
const res = await ProductApi.getProduct(route.query.id)
|
||||
const res = await ProductApi.getProduct(id)
|
||||
let diyField = {}
|
||||
if (res.diyParams) {
|
||||
diyField = isObject(res.diyParams) ? res.diyParams : JSON.parse(res.diyParams)
|
||||
|
||||
@@ -2,21 +2,16 @@
|
||||
<div>
|
||||
<el-form :model="searchForm" ref="searchRef" inline label-width="0">
|
||||
<el-form-item>
|
||||
<el-input
|
||||
v-model="searchForm.schoolName"
|
||||
placeholder="请输入驾校名称"
|
||||
<el-cascader
|
||||
:options="schoolOption"
|
||||
v-model="searchForm.schPlace"
|
||||
clearable
|
||||
style="width: 180px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input
|
||||
v-model="searchForm.placeName"
|
||||
placeholder="请输入场地名称"
|
||||
clearable
|
||||
style="width: 180px"
|
||||
@keyup.enter="handleQuery"
|
||||
filterable
|
||||
show-all-levels
|
||||
style="width: 300px"
|
||||
placeholder="选择驾校/场地"
|
||||
:props="{ expandTrigger: 'hover', multiple: false, checkStrictly: true }"
|
||||
@change="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
@@ -69,85 +64,67 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6" :offset="0">
|
||||
<div class="head-container" style="max-height: 700px; overflow-y: auto">
|
||||
<el-tree
|
||||
ref="tree"
|
||||
:data="schoolOption"
|
||||
accordion
|
||||
node-key="id"
|
||||
highlight-current
|
||||
:default-expanded-keys="selectNodes.map((item) => item.id)"
|
||||
@node-click="handleNodeClick"
|
||||
<el-table
|
||||
:data="tableList"
|
||||
v-loading="loading"
|
||||
border
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="50" />
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column
|
||||
v-for="col in columns"
|
||||
:prop="col.props"
|
||||
:key="col.props"
|
||||
:label="col.label"
|
||||
:width="col.width"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column label="备注" width="260">
|
||||
<template #default="{ row }">
|
||||
<div v-dompurify-html="row.remark"></div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="80">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-model="row.status"
|
||||
:active-value="0"
|
||||
:inactive-value="1"
|
||||
:disabled="!checkPermi(['school:class:update'])"
|
||||
@change="handleChangeStatus(row)"
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="18" :offset="0">
|
||||
<el-table
|
||||
:data="tableList"
|
||||
v-loading="loading"
|
||||
border
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="50" />
|
||||
<el-table-column type="index" label="序号" width="60" />
|
||||
<el-table-column
|
||||
v-for="col in columns"
|
||||
:prop="col.props"
|
||||
:key="col.props"
|
||||
:label="col.label"
|
||||
:width="col.width"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column label="备注" width="260">
|
||||
<template #default="{ row }">
|
||||
<div v-dompurify-html="row.remark"></div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="80">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-model="row.status"
|
||||
:active-value="0"
|
||||
:inactive-value="1"
|
||||
:disabled="!checkPermi(['school:class:update'])"
|
||||
@change="handleChangeStatus(row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="120px">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
style="padding: 0"
|
||||
text
|
||||
v-hasPermi="['school:class:update']"
|
||||
@click="handleOpenDialog('update', row.typeId)"
|
||||
>
|
||||
修改
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
style="padding: 0"
|
||||
text
|
||||
v-hasPermi="['school:class:delete']"
|
||||
@click="handleRemove(row.typeId)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
v-model:limit="searchForm.pageSize"
|
||||
v-model:page="searchForm.pageNo"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="120px">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
style="padding: 0"
|
||||
text
|
||||
v-hasPermi="['school:class:update']"
|
||||
@click="handleOpenDialog('update', row.typeId)"
|
||||
>
|
||||
修改
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
style="padding: 0"
|
||||
text
|
||||
v-hasPermi="['school:class:delete']"
|
||||
@click="handleRemove(row.typeId)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<Pagination
|
||||
v-model:limit="searchForm.pageSize"
|
||||
v-model:page="searchForm.pageNo"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<Dialog title="批量修改" v-model="batchStatusDialogShow" width="400px">
|
||||
<el-form :model="statusForm" ref="statusRef" label-width="80px">
|
||||
<el-form-item label="选择状态" prop="status">
|
||||
@@ -186,8 +163,7 @@ const total = ref(0)
|
||||
const tableList = ref([])
|
||||
|
||||
const searchForm = ref({
|
||||
schoolName: undefined,
|
||||
placeName: undefined,
|
||||
schPlace: undefined,
|
||||
typeName: undefined,
|
||||
licenseType: undefined,
|
||||
pageNo: 1,
|
||||
@@ -195,41 +171,24 @@ const searchForm = ref({
|
||||
})
|
||||
|
||||
const schoolOption = ref([])
|
||||
const selectNodes = ref([])
|
||||
// const selectNodes = ref([])
|
||||
|
||||
async function getSchoolList() {
|
||||
try {
|
||||
const data = await PlaceApi.getPlaceList()
|
||||
schoolOption.value = data.schoolList.map((item) => ({
|
||||
id: item.schoolId,
|
||||
value: item.schoolId,
|
||||
label: item.schoolName,
|
||||
level: 1,
|
||||
children: data.placeList
|
||||
.filter((place) => item.schoolId === place.schoolId)
|
||||
.map((place) => ({
|
||||
id: place.placeId,
|
||||
label: place.name,
|
||||
level: 2
|
||||
value: place.placeId,
|
||||
label: place.name
|
||||
}))
|
||||
}))
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function handleNodeClick(data, node) {
|
||||
if (data.level === 1) {
|
||||
selectNodes.value = [{ id: data.id, name: data.label }]
|
||||
searchForm.value.schoolName = data.label
|
||||
} else {
|
||||
selectNodes.value = [
|
||||
{ id: node.parent.data.id, name: node.parent.data.label },
|
||||
{ id: data.id, name: data.label }
|
||||
]
|
||||
searchForm.value.schoolName = node.parent.data.label
|
||||
searchForm.value.placeName = data.label
|
||||
}
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{ props: 'schoolName', label: '驾校', width: '100px' },
|
||||
{ props: 'placeName', label: '场地' },
|
||||
@@ -248,7 +207,15 @@ function handleQuery() {
|
||||
async function getList() {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await ClassApi.getClassTypePage(searchForm.value)
|
||||
const params = { ...searchForm.value }
|
||||
if (params.schPlace && params.schPlace.length) {
|
||||
params.schoolId = params.schPlace[0]
|
||||
if (params.schPlace.length == 2) {
|
||||
params.placeId = params.schPlace[1]
|
||||
}
|
||||
}
|
||||
delete params.schPlace
|
||||
const data = await ClassApi.getClassTypePage(params)
|
||||
tableList.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
@@ -263,8 +230,7 @@ function handleOpenDialog(type, id = null) {
|
||||
|
||||
function handleReset() {
|
||||
searchForm.value = {
|
||||
schoolName: undefined,
|
||||
placeName: undefined,
|
||||
schPlace: undefined,
|
||||
typeName: undefined,
|
||||
licenseType: undefined,
|
||||
pageNo: 1,
|
||||
|
||||
Reference in New Issue
Block a user