【线索管理】 新增# 线索管理
parent
4221095b2c
commit
3793f8d8ab
|
@ -0,0 +1,46 @@
|
||||||
|
<template>
|
||||||
|
<el-drawer v-model="drawerVisible" :title="parameter.title" :size="parameter.width">
|
||||||
|
<slot />
|
||||||
|
<template #footer>
|
||||||
|
<el-button @click="handleCancel">取消</el-button>
|
||||||
|
<el-button type="primary" @click="handleConfirm">确认</el-button>
|
||||||
|
</template>
|
||||||
|
</el-drawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
export interface IParams {
|
||||||
|
title: string
|
||||||
|
width?: string | number
|
||||||
|
data: { [key: string]: any }
|
||||||
|
}
|
||||||
|
const emit = defineEmits(['handleCancel', 'handleConfirm'])
|
||||||
|
|
||||||
|
const drawerVisible = ref(false)
|
||||||
|
|
||||||
|
// 父组件传递过来的参数
|
||||||
|
const parameter = ref<IParams>({
|
||||||
|
title: '',
|
||||||
|
width: '50%',
|
||||||
|
data: {}
|
||||||
|
})
|
||||||
|
const openDrawer = (params: IParams) => {
|
||||||
|
parameter.value = { ...parameter.value, ...params }
|
||||||
|
drawerVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('handleCancel', closeDrawer)
|
||||||
|
}
|
||||||
|
const handleConfirm = () => {
|
||||||
|
emit('handleConfirm', closeDrawer)
|
||||||
|
}
|
||||||
|
const closeDrawer = () => {
|
||||||
|
drawerVisible.value = false
|
||||||
|
}
|
||||||
|
defineExpose({
|
||||||
|
openDrawer,
|
||||||
|
drawerVisible
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style scoped></style>
|
|
@ -10,6 +10,7 @@ import directives from './directives'
|
||||||
// 表格组件
|
// 表格组件
|
||||||
import ProTable from '@/components/ProTable/index.vue'
|
import ProTable from '@/components/ProTable/index.vue'
|
||||||
import ProDialog from '@/components/ProDialog/index.vue'
|
import ProDialog from '@/components/ProDialog/index.vue'
|
||||||
|
import ProDrawer from '@/components/ProDrawer/index.vue'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
app.use(install)
|
app.use(install)
|
||||||
|
@ -17,4 +18,5 @@ app.use(eventBus)
|
||||||
app.use(directives)
|
app.use(directives)
|
||||||
app.component('ProTable', ProTable)
|
app.component('ProTable', ProTable)
|
||||||
app.component('ProDialog', ProDialog)
|
app.component('ProDialog', ProDialog)
|
||||||
|
app.component('ProDrawer', ProDrawer)
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
--el-text-color-secondary: #999999;
|
--el-text-color-secondary: #999999;
|
||||||
--el-text-color-placeholder: #a8abb2;
|
--el-text-color-placeholder: #a8abb2;
|
||||||
--el-text-color-disabled: #c0c4cc;
|
--el-text-color-disabled: #c0c4cc;
|
||||||
|
--el-text-color-black2: #979797;
|
||||||
--el-border-color: #dcdfe6;
|
--el-border-color: #dcdfe6;
|
||||||
--el-border-color-light: #e4e7ed;
|
--el-border-color-light: #e4e7ed;
|
||||||
--el-border-color-lighter: #ebeef5;
|
--el-border-color-lighter: #ebeef5;
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
<template>
|
||||||
|
<div class="edit-popup">
|
||||||
|
<popup
|
||||||
|
ref="popupRef"
|
||||||
|
:title="popupTitle"
|
||||||
|
:async="true"
|
||||||
|
width="550px"
|
||||||
|
@confirm="handleSubmit"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<el-form ref="formRef" :model="formData" label-width="84px" :rules="formRules">
|
||||||
|
<el-form-item label="上级部门" prop="pid" v-if="formData.pid !== 0">
|
||||||
|
<el-tree-select
|
||||||
|
class="flex-1"
|
||||||
|
v-model="formData.pid"
|
||||||
|
:data="optionsData.dept"
|
||||||
|
clearable
|
||||||
|
node-key="id"
|
||||||
|
:props="{
|
||||||
|
value: 'id',
|
||||||
|
label: 'name'
|
||||||
|
}"
|
||||||
|
check-strictly
|
||||||
|
:default-expand-all="true"
|
||||||
|
placeholder="请选择上级部门"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="部门名称" prop="name">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.name"
|
||||||
|
placeholder="请输入部门名称"
|
||||||
|
clearable
|
||||||
|
:maxlength="100"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="负责人" prop="duty">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.duty"
|
||||||
|
placeholder="请输入负责人姓名"
|
||||||
|
clearable
|
||||||
|
:maxlength="30"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="联系电话" prop="mobile">
|
||||||
|
<el-input v-model="formData.mobile" placeholder="请输入联系电话" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="排序" prop="sort">
|
||||||
|
<div>
|
||||||
|
<el-input-number v-model="formData.sort" :min="0" :max="9999" />
|
||||||
|
<div class="form-tips">默认为0, 数值越大越排前</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="部门状态" prop="isStop">
|
||||||
|
<el-switch v-model="formData.isStop" :active-value="0" :inactive-value="1" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</popup>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { FormInstance } from 'element-plus'
|
||||||
|
import { deptLists, deptEdit, deptAdd, deptDetail } from '@/api/org/department'
|
||||||
|
import Popup from '@/components/popup/index.vue'
|
||||||
|
import { useDictOptions } from '@/hooks/useDictOptions'
|
||||||
|
import feedback from '@/utils/feedback'
|
||||||
|
const emit = defineEmits(['success', 'close'])
|
||||||
|
const formRef = shallowRef<FormInstance>()
|
||||||
|
const popupRef = shallowRef<InstanceType<typeof Popup>>()
|
||||||
|
const mode = ref('add')
|
||||||
|
const popupTitle = computed(() => {
|
||||||
|
return mode.value == 'edit' ? '编辑部门' : '新增部门'
|
||||||
|
})
|
||||||
|
const formData = reactive({
|
||||||
|
id: '',
|
||||||
|
pid: '' as string | number,
|
||||||
|
name: '',
|
||||||
|
duty: '',
|
||||||
|
mobile: '',
|
||||||
|
sort: 0,
|
||||||
|
isStop: 0
|
||||||
|
})
|
||||||
|
const checkMobile = (rule: any, value: any, callback: any) => {
|
||||||
|
if (!value) {
|
||||||
|
return callback()
|
||||||
|
} else {
|
||||||
|
const reg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/
|
||||||
|
console.log(reg.test(value))
|
||||||
|
if (reg.test(value)) {
|
||||||
|
callback()
|
||||||
|
} else {
|
||||||
|
return callback(new Error('请输入正确的手机号'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const formRules = {
|
||||||
|
pid: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请选择上级部门',
|
||||||
|
trigger: ['change']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入部门名称',
|
||||||
|
trigger: ['blur']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
duty: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入负责人',
|
||||||
|
trigger: ['blur']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
mobile: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入联系电话',
|
||||||
|
trigger: ['blur']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const { optionsData } = useDictOptions<{
|
||||||
|
dept: any[]
|
||||||
|
}>({
|
||||||
|
dept: {
|
||||||
|
api: deptLists
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
await formRef.value?.validate()
|
||||||
|
mode.value == 'edit' ? await deptEdit(formData) : await deptAdd(formData)
|
||||||
|
popupRef.value?.close()
|
||||||
|
feedback.msgSuccess('操作成功')
|
||||||
|
emit('success')
|
||||||
|
}
|
||||||
|
|
||||||
|
const open = (type = 'add') => {
|
||||||
|
mode.value = type
|
||||||
|
popupRef.value?.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
const setFormData = (data: Record<any, any>) => {
|
||||||
|
for (const key in formData) {
|
||||||
|
if (data[key] != null && data[key] != undefined) {
|
||||||
|
//@ts-ignore
|
||||||
|
formData[key] = data[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getDetail = async (row: Record<string, any>) => {
|
||||||
|
const data = await deptDetail({
|
||||||
|
id: row.id
|
||||||
|
})
|
||||||
|
setFormData(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
emit('close')
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open,
|
||||||
|
setFormData,
|
||||||
|
getDetail
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -0,0 +1,166 @@
|
||||||
|
<template>
|
||||||
|
<div class="dept-lists">
|
||||||
|
<el-card class="!border-none" shadow="never">
|
||||||
|
<el-form ref="formRef" class="mb-[-16px]" :model="queryParams" :inline="true">
|
||||||
|
<el-form-item label="部门名称" prop="name">
|
||||||
|
<el-input
|
||||||
|
class="w-[280px]"
|
||||||
|
v-model="queryParams.name"
|
||||||
|
clearable
|
||||||
|
@keyup.enter="getLists"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="部门状态" prop="isStop">
|
||||||
|
<el-select class="w-[280px]" v-model="queryParams.isStop">
|
||||||
|
<el-option label="全部" value />
|
||||||
|
<el-option label="正常" value="0" />
|
||||||
|
<el-option label="停用" value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="getLists">查询</el-button>
|
||||||
|
<el-button @click="resetParams">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="!border-none mt-4" shadow="never">
|
||||||
|
<div>
|
||||||
|
<el-button v-perms="['system:dept:add']" type="primary" @click="handleAdd()">
|
||||||
|
<template #icon>
|
||||||
|
<icon name="el-icon-Plus" />
|
||||||
|
</template>
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="handleExpand"> 展开/折叠 </el-button>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
ref="tableRef"
|
||||||
|
class="mt-4"
|
||||||
|
size="large"
|
||||||
|
v-loading="loading"
|
||||||
|
:data="lists"
|
||||||
|
row-key="id"
|
||||||
|
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
label="部门名称"
|
||||||
|
prop="name"
|
||||||
|
min-width="150"
|
||||||
|
show-overflow-tooltip
|
||||||
|
/>
|
||||||
|
<el-table-column label="部门状态" prop="isStop" min-width="100">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag class="ml-2" :type="row.isStop ? 'danger' : ''">
|
||||||
|
{{ row.isStop ? '停用' : '正常' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="排序" prop="sort" min-width="100" />
|
||||||
|
<el-table-column label="更新时间" prop="updateTime" min-width="180" />
|
||||||
|
<el-table-column label="操作" width="160" fixed="right">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button
|
||||||
|
v-perms="['system:dept:add']"
|
||||||
|
type="primary"
|
||||||
|
link
|
||||||
|
@click="handleAdd(row.id)"
|
||||||
|
>
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-perms="['system:dept:edit']"
|
||||||
|
type="primary"
|
||||||
|
link
|
||||||
|
@click="handleEdit(row)"
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-if="row.pid !== 0"
|
||||||
|
v-perms="['system:dept:del']"
|
||||||
|
type="danger"
|
||||||
|
link
|
||||||
|
@click="handleDelete(row.id)"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-card>
|
||||||
|
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup name="department">
|
||||||
|
import type { ElTable, FormInstance } from 'element-plus'
|
||||||
|
import EditPopup from './edit.vue'
|
||||||
|
import { deptDelete, deptLists } from '@/api/org/department'
|
||||||
|
import feedback from '@/utils/feedback'
|
||||||
|
const tableRef = shallowRef<InstanceType<typeof ElTable>>()
|
||||||
|
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
|
||||||
|
const formRef = shallowRef<FormInstance>()
|
||||||
|
let isExpand = false
|
||||||
|
const loading = ref(false)
|
||||||
|
const lists = ref<any[]>([])
|
||||||
|
const queryParams = reactive({
|
||||||
|
isStop: '',
|
||||||
|
name: ''
|
||||||
|
})
|
||||||
|
const showEdit = ref(false)
|
||||||
|
const getLists = async () => {
|
||||||
|
loading.value = true
|
||||||
|
lists.value = await deptLists(queryParams)
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetParams = () => {
|
||||||
|
formRef.value?.resetFields()
|
||||||
|
getLists()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAdd = async (id?: number) => {
|
||||||
|
showEdit.value = true
|
||||||
|
await nextTick()
|
||||||
|
if (id) {
|
||||||
|
editRef.value?.setFormData({
|
||||||
|
pid: id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
editRef.value?.open('add')
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEdit = async (data: any) => {
|
||||||
|
showEdit.value = true
|
||||||
|
await nextTick()
|
||||||
|
editRef.value?.open('edit')
|
||||||
|
editRef.value?.getDetail(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDelete = async (id: number) => {
|
||||||
|
await feedback.confirm('确定要删除?')
|
||||||
|
await deptDelete({ id })
|
||||||
|
feedback.msgSuccess('删除成功')
|
||||||
|
getLists()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleExpand = () => {
|
||||||
|
isExpand = !isExpand
|
||||||
|
toggleExpand(lists.value, isExpand)
|
||||||
|
}
|
||||||
|
|
||||||
|
const toggleExpand = (children: any[], unfold = true) => {
|
||||||
|
for (const key in children) {
|
||||||
|
tableRef.value?.toggleRowExpansion(children[key], unfold)
|
||||||
|
if (children[key].children) {
|
||||||
|
toggleExpand(children[key].children!, unfold)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await getLists()
|
||||||
|
nextTick(() => {
|
||||||
|
handleExpand()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -0,0 +1,120 @@
|
||||||
|
<template>
|
||||||
|
<div class="edit-popup">
|
||||||
|
<popup
|
||||||
|
ref="popupRef"
|
||||||
|
:title="popupTitle"
|
||||||
|
:async="true"
|
||||||
|
width="550px"
|
||||||
|
@confirm="handleSubmit"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<el-form ref="formRef" :model="formData" label-width="84px" :rules="formRules">
|
||||||
|
<el-form-item label="岗位名称" prop="name">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.name"
|
||||||
|
placeholder="请输入岗位名称"
|
||||||
|
clearable
|
||||||
|
:maxlength="100"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="岗位编码" prop="code">
|
||||||
|
<el-input v-model="formData.code" placeholder="请输入岗位编码" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="排序" prop="sort">
|
||||||
|
<div>
|
||||||
|
<el-input-number v-model="formData.sort" :min="0" :max="9999" />
|
||||||
|
<div class="form-tips">默认为0, 数值越大越排前</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="remarks">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.remarks"
|
||||||
|
placeholder="请输入备注"
|
||||||
|
type="textarea"
|
||||||
|
:autosize="{ minRows: 4, maxRows: 6 }"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="岗位状态" prop="isStop">
|
||||||
|
<el-switch v-model="formData.isStop" :active-value="0" :inactive-value="1" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</popup>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type { FormInstance } from 'element-plus'
|
||||||
|
import { postEdit, postAdd, postDetail } from '@/api/org/post'
|
||||||
|
import Popup from '@/components/popup/index.vue'
|
||||||
|
import feedback from '@/utils/feedback'
|
||||||
|
const emit = defineEmits(['success', 'close'])
|
||||||
|
const formRef = shallowRef<FormInstance>()
|
||||||
|
const popupRef = shallowRef<InstanceType<typeof Popup>>()
|
||||||
|
const mode = ref('add')
|
||||||
|
const popupTitle = computed(() => {
|
||||||
|
return mode.value == 'edit' ? '编辑岗位' : '新增岗位'
|
||||||
|
})
|
||||||
|
const formData = reactive({
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
code: '',
|
||||||
|
sort: 0,
|
||||||
|
remarks: '',
|
||||||
|
isStop: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
const formRules = {
|
||||||
|
code: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入岗位编码',
|
||||||
|
trigger: ['blur']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
name: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '请输入岗位名称',
|
||||||
|
trigger: ['blur']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
await formRef.value?.validate()
|
||||||
|
mode.value == 'edit' ? await postEdit(formData) : await postAdd(formData)
|
||||||
|
feedback.msgSuccess('操作成功')
|
||||||
|
popupRef.value?.close()
|
||||||
|
emit('success')
|
||||||
|
}
|
||||||
|
|
||||||
|
const open = (type = 'add') => {
|
||||||
|
mode.value = type
|
||||||
|
popupRef.value?.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
const setFormData = (data: Record<any, any>) => {
|
||||||
|
for (const key in formData) {
|
||||||
|
if (data[key] != null && data[key] != undefined) {
|
||||||
|
//@ts-ignore
|
||||||
|
formData[key] = data[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getDetail = async (row: Record<string, any>) => {
|
||||||
|
const data = await postDetail({
|
||||||
|
id: row.id
|
||||||
|
})
|
||||||
|
setFormData(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
emit('close')
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
open,
|
||||||
|
setFormData,
|
||||||
|
getDetail
|
||||||
|
})
|
||||||
|
</script>
|
|
@ -0,0 +1,128 @@
|
||||||
|
<template>
|
||||||
|
<div class="post-lists">
|
||||||
|
<el-card class="!border-none" shadow="never">
|
||||||
|
<el-form ref="formRef" class="mb-[-16px]" :model="queryParams" :inline="true">
|
||||||
|
<el-form-item label="岗位编码">
|
||||||
|
<el-input
|
||||||
|
class="w-[280px]"
|
||||||
|
v-model="queryParams.code"
|
||||||
|
clearable
|
||||||
|
@keyup.enter="resetPage"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="岗位名称">
|
||||||
|
<el-input
|
||||||
|
class="w-[280px]"
|
||||||
|
v-model="queryParams.name"
|
||||||
|
clearable
|
||||||
|
@keyup.enter="resetPage"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="岗位状态">
|
||||||
|
<el-select class="w-[280px]" v-model="queryParams.isStop">
|
||||||
|
<el-option label="全部" value />
|
||||||
|
<el-option label="正常" :value="0" />
|
||||||
|
<el-option label="停用" :value="1" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="resetPage">查询</el-button>
|
||||||
|
<el-button @click="resetParams">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
<el-card class="!border-none mt-4" shadow="never">
|
||||||
|
<div>
|
||||||
|
<el-button v-perms="['system:post:add']" type="primary" @click="handleAdd()">
|
||||||
|
<template #icon>
|
||||||
|
<icon name="el-icon-Plus" />
|
||||||
|
</template>
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table class="mt-4" size="large" v-loading="pager.loading" :data="pager.lists">
|
||||||
|
<el-table-column label="岗位编码" prop="code" min-width="100" />
|
||||||
|
<el-table-column label="岗位名称" prop="name" min-width="100" />
|
||||||
|
<el-table-column label="排序" prop="sort" min-width="100" />
|
||||||
|
<el-table-column
|
||||||
|
label="备注"
|
||||||
|
prop="remarks"
|
||||||
|
min-width="100"
|
||||||
|
show-overflow-tooltip
|
||||||
|
/>
|
||||||
|
<el-table-column label="添加时间" prop="createTime" min-width="180" />
|
||||||
|
<el-table-column label="岗位状态" prop="isStop" min-width="100">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag class="ml-2" :type="row.isStop ? 'danger' : ''">
|
||||||
|
{{ row.isStop ? '停用' : '正常' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="120" fixed="right">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button
|
||||||
|
v-perms="['system:post:edit']"
|
||||||
|
type="primary"
|
||||||
|
link
|
||||||
|
@click="handleEdit(row)"
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
v-perms="['system:post:del']"
|
||||||
|
type="danger"
|
||||||
|
link
|
||||||
|
@click="handleDelete(row.id)"
|
||||||
|
>
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="flex justify-end mt-4">
|
||||||
|
<pagination v-model="pager" @change="getLists" />
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup name="post">
|
||||||
|
import { postDelete, postLists } from '@/api/org/post'
|
||||||
|
import { usePaging } from '@/hooks/usePaging'
|
||||||
|
import feedback from '@/utils/feedback'
|
||||||
|
import EditPopup from './edit.vue'
|
||||||
|
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
|
||||||
|
const showEdit = ref(false)
|
||||||
|
const queryParams = reactive({
|
||||||
|
code: '',
|
||||||
|
name: '',
|
||||||
|
isStop: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const { pager, getLists, resetPage, resetParams } = usePaging({
|
||||||
|
fetchFun: postLists,
|
||||||
|
params: queryParams
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleAdd = async () => {
|
||||||
|
showEdit.value = true
|
||||||
|
await nextTick()
|
||||||
|
editRef.value?.open('add')
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEdit = async (data: any) => {
|
||||||
|
showEdit.value = true
|
||||||
|
await nextTick()
|
||||||
|
editRef.value?.open('edit')
|
||||||
|
editRef.value?.getDetail(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDelete = async (id: number) => {
|
||||||
|
await feedback.confirm('确定要删除?')
|
||||||
|
await postDelete({ id })
|
||||||
|
feedback.msgSuccess('删除成功')
|
||||||
|
getLists()
|
||||||
|
}
|
||||||
|
|
||||||
|
getLists()
|
||||||
|
</script>
|
|
@ -19,11 +19,12 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="岗位">
|
<el-form-item label="岗位">
|
||||||
<el-checkbox-group v-model="form.position">
|
<el-checkbox-group v-model="form.position">
|
||||||
<el-checkbox v-for="option in positionOptions" :key="option.value" :value="option.value" name="type">
|
<el-checkbox v-for="option in positionOptions" :key="option.value" :label="option.value" name="type">
|
||||||
{{ option.label }}
|
{{ option.label }}
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<template v-if="form.position.includes(1)">
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="flex items-center gap-[6px] cursor-pointer">
|
<div class="flex items-center gap-[6px] cursor-pointer">
|
||||||
|
@ -52,6 +53,7 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
</template>
|
||||||
<el-form-item label="账号状态">
|
<el-form-item label="账号状态">
|
||||||
<el-radio-group v-model="form.accountStatus">
|
<el-radio-group v-model="form.accountStatus">
|
||||||
<el-radio v-for="option in accountStatusOptions" :key="option.value" :label="option.value">{{ option.label }}</el-radio>
|
<el-radio v-for="option in accountStatusOptions" :key="option.value" :label="option.value">{{ option.label }}</el-radio>
|
||||||
|
@ -65,6 +67,7 @@
|
||||||
import ProDialog, { type IParams } from '@/components/ProDialog/index.vue'
|
import ProDialog, { type IParams } from '@/components/ProDialog/index.vue'
|
||||||
const proDialogRef = ref<InstanceType<typeof ProDialog>>()
|
const proDialogRef = ref<InstanceType<typeof ProDialog>>()
|
||||||
|
|
||||||
|
const emit = defineEmits(['fetchTableList'])
|
||||||
const data = ref([
|
const data = ref([
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
|
@ -127,7 +130,7 @@ const form = ref({
|
||||||
organization: '',
|
organization: '',
|
||||||
accountName: '',
|
accountName: '',
|
||||||
mobile: '',
|
mobile: '',
|
||||||
position: '',
|
position: [],
|
||||||
channel: '',
|
channel: '',
|
||||||
accountStatus: '',
|
accountStatus: '',
|
||||||
teacher: ''
|
teacher: ''
|
||||||
|
@ -140,6 +143,7 @@ const handleCancel = (callback: () => void) => {
|
||||||
}
|
}
|
||||||
const handleConfirm = (callback: () => void) => {
|
const handleConfirm = (callback: () => void) => {
|
||||||
callback()
|
callback()
|
||||||
|
emit('fetchTableList')
|
||||||
}
|
}
|
||||||
defineExpose({
|
defineExpose({
|
||||||
openDialog
|
openDialog
|
||||||
|
|
|
@ -1,125 +0,0 @@
|
||||||
<template>
|
|
||||||
<el-dialog v-model="dialogVisible" :title="parameter.title" :width="parameter.width">
|
|
||||||
<el-space direction="vertical" alignment="normal">
|
|
||||||
<el-form :model="searchForm" ref="userFormRef" :inline="true" label-width="auto" @submit.native.prevent>
|
|
||||||
<el-form-item label="账号名称">
|
|
||||||
<el-input class="ls-input" v-model="searchForm.accountName" placeholder="请输入账号名称" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary">搜索</el-button>
|
|
||||||
<el-button>重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<ProTable ref="proTableRef" :columns="columns" :tableData="tableData" :loading="loading" :maxHeight="530">
|
|
||||||
<template #radio="{ row }">
|
|
||||||
<el-radio v-model="radio" :label="row.id"> </el-radio>
|
|
||||||
</template>
|
|
||||||
<template #accountName="{ row }">
|
|
||||||
<el-space>
|
|
||||||
<span>{{ row.accountName }}</span>
|
|
||||||
<span
|
|
||||||
v-if="isGroupLeader(row.groupLeader)"
|
|
||||||
class="px-[6px] text-green border border-solid border-green rounded-[4px] text-center text-xs"
|
|
||||||
>
|
|
||||||
组长
|
|
||||||
</span>
|
|
||||||
</el-space>
|
|
||||||
</template>
|
|
||||||
<template #accountStatus="{ row }">
|
|
||||||
<el-switch v-model="row.accountStatus" disabled :active-value="1" :inactive-value="0" />
|
|
||||||
</template>
|
|
||||||
</ProTable>
|
|
||||||
<!-- <pagination v-model="pager" @change="getLists" layout="total, prev, pager, next, jumper" class="mb-[10px]" /> -->
|
|
||||||
</el-space>
|
|
||||||
<template #footer>
|
|
||||||
<el-button @click="handleCancel">取消</el-button>
|
|
||||||
<el-button type="primary" @click="handleConfirm">确认</el-button>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
interface IParams {
|
|
||||||
title: string
|
|
||||||
width?: string | number
|
|
||||||
data: { [key: string]: any }
|
|
||||||
}
|
|
||||||
|
|
||||||
const dialogVisible = ref(false)
|
|
||||||
// 父组件传递过来的参数
|
|
||||||
const parameter = ref<IParams>({
|
|
||||||
title: '',
|
|
||||||
width: '50%',
|
|
||||||
data: {}
|
|
||||||
})
|
|
||||||
const openDialog = (params: IParams) => {
|
|
||||||
parameter.value = { ...parameter.value, ...params }
|
|
||||||
dialogVisible.value = true
|
|
||||||
}
|
|
||||||
const emit = defineEmits(['refreshList'])
|
|
||||||
defineExpose({
|
|
||||||
openDialog
|
|
||||||
})
|
|
||||||
const searchForm = ref({
|
|
||||||
accountName: ''
|
|
||||||
})
|
|
||||||
|
|
||||||
const loading = ref(false)
|
|
||||||
const proTableRef = ref()
|
|
||||||
const tableData = ref<any[]>([])
|
|
||||||
const columns = reactive([
|
|
||||||
{ prop: 'radio', label: '单选', width: 70 },
|
|
||||||
{ prop: 'accountName', label: '账号名称' },
|
|
||||||
{ prop: 'mobile', label: '联系电话' },
|
|
||||||
{ prop: 'organization', label: '所属组织' },
|
|
||||||
{ prop: 'position', label: '岗位' },
|
|
||||||
{ prop: 'accountStatus', label: '账号状态' }
|
|
||||||
])
|
|
||||||
const radio = ref()
|
|
||||||
const isGroupLeader = computed(() => (groupLeader: number) => groupLeader == 1)
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => dialogVisible.value,
|
|
||||||
val => {
|
|
||||||
if (val) {
|
|
||||||
loading.value = true
|
|
||||||
setTimeout(() => {
|
|
||||||
tableData.value = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
accountName: '张三',
|
|
||||||
mobile: '18138952909',
|
|
||||||
organization: '广州团队-A组',
|
|
||||||
position: '电销老师',
|
|
||||||
accountStatus: 1,
|
|
||||||
groupLeader: 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
accountName: '李四',
|
|
||||||
mobile: '18138952909',
|
|
||||||
organization: '广州团队-A组',
|
|
||||||
position: '电销老师',
|
|
||||||
accountStatus: 1,
|
|
||||||
groupLeader: 0
|
|
||||||
}
|
|
||||||
]
|
|
||||||
loading.value = false
|
|
||||||
// 如果已设置组长,则需要默认回显
|
|
||||||
if (tableData.value.length > 0) {
|
|
||||||
radio.value = tableData.value.find(item => item.groupLeader == 1)?.id
|
|
||||||
}
|
|
||||||
}, 500)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
const handleCancel = () => {
|
|
||||||
dialogVisible.value = false
|
|
||||||
}
|
|
||||||
const handleConfirm = () => {
|
|
||||||
console.log(radio.value)
|
|
||||||
dialogVisible.value = false
|
|
||||||
emit('refreshList')
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style scoped></style>
|
|
|
@ -9,15 +9,15 @@
|
||||||
<el-button type="danger" plain :icon="Delete" :disabled="isDisabled" @click="handleBatchDelete">批量删除</el-button>
|
<el-button type="danger" plain :icon="Delete" :disabled="isDisabled" @click="handleBatchDelete">批量删除</el-button>
|
||||||
</el-space>
|
</el-space>
|
||||||
<el-space>
|
<el-space>
|
||||||
<el-input :placeholder="`请输入${placeholder}`">
|
<el-input :placeholder="`请输入${placeholder}`" v-model="searchForm.keyword" @input="handleInputChange">
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<el-select v-model="selectKey" :placeholder="placeholder" class="w-[100px]">
|
<el-select v-model="selectKey" :placeholder="placeholder" class="w-[100px]">
|
||||||
<el-option v-for="option in searchOptions" :key="option.field" :label="option.label" :value="option.field" />
|
<el-option v-for="option in searchOptions" :key="option.field" :label="option.label" :value="option.field" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
<el-select placeholder="请选择账号状态">
|
<el-select placeholder="请选择账号状态" v-model="searchForm.accountStatus" clearable @change="handleSelectChange">
|
||||||
<el-option label="Restaurant" value="1" />
|
<el-option v-for="option in accountStatusOptions" :key="option.value" :label="option.label" :value="option.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-space>
|
</el-space>
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
</template>
|
</template>
|
||||||
</ProTable>
|
</ProTable>
|
||||||
</div>
|
</div>
|
||||||
<account-dialog ref="accountDialogRef" />
|
<account-dialog ref="accountDialogRef" @fetch-table-list="fetchTableList" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -52,6 +52,7 @@ import useHandleData from '@/hooks/useHandleData'
|
||||||
import feedback from '@/utils/feedback'
|
import feedback from '@/utils/feedback'
|
||||||
import { Plus, Delete } from '@element-plus/icons-vue'
|
import { Plus, Delete } from '@element-plus/icons-vue'
|
||||||
import accountDialog from '../components/account-list/account-dialog.vue'
|
import accountDialog from '../components/account-list/account-dialog.vue'
|
||||||
|
import { useDebounceFn } from '@vueuse/core'
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
curOrganization: {
|
curOrganization: {
|
||||||
|
@ -66,7 +67,10 @@ const searchOptions = shallowRef([
|
||||||
{ field: 'positionName', label: '岗位名称' }
|
{ field: 'positionName', label: '岗位名称' }
|
||||||
])
|
])
|
||||||
const placeholder = computed(() => searchOptions.value.find(item => item.field == selectKey.value)?.label)
|
const placeholder = computed(() => searchOptions.value.find(item => item.field == selectKey.value)?.label)
|
||||||
|
const accountStatusOptions = ref([
|
||||||
|
{ label: '启用', value: 1 },
|
||||||
|
{ label: '停用', value: 2 }
|
||||||
|
])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const proTableRef = ref()
|
const proTableRef = ref()
|
||||||
const tableData = ref<any[]>([])
|
const tableData = ref<any[]>([])
|
||||||
|
@ -158,5 +162,28 @@ const showAccountDialog = () => {
|
||||||
data: {}
|
data: {}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const searchForm = ref({
|
||||||
|
keyword: '',
|
||||||
|
accountStatus: ''
|
||||||
|
})
|
||||||
|
const handleInputChange = useDebounceFn(() => {
|
||||||
|
const formMap: Record<string, string> = {
|
||||||
|
accountName: '',
|
||||||
|
mobile: '',
|
||||||
|
position: ''
|
||||||
|
}
|
||||||
|
formMap[selectKey.value] = searchForm.value.keyword
|
||||||
|
}, 500)
|
||||||
|
const handleSelectChange = () => {
|
||||||
|
console.log('handleSelectChange')
|
||||||
|
}
|
||||||
|
watch(
|
||||||
|
() => selectKey.value,
|
||||||
|
(newVal, oldVal) => {
|
||||||
|
if (newVal != oldVal && searchForm.value.keyword !== '') {
|
||||||
|
searchForm.value.keyword = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
<template>
|
||||||
|
<el-space direction="vertical" alignment="normal" :size="24" v-loading="loading">
|
||||||
|
<el-descriptions v-for="item in baseInfo" :key="item.title" :title="item.title" direction="vertical" :column="4" border>
|
||||||
|
<el-descriptions-item v-for="(itemy, indey) in item.data" :key="indey" :label="itemy.label">{{ itemy.value }}</el-descriptions-item>
|
||||||
|
</el-descriptions>
|
||||||
|
</el-space>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
default: 'baseInfo'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const loading = ref(false)
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
() => {
|
||||||
|
console.log('基础信息')
|
||||||
|
loading.value = true
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = false
|
||||||
|
}, 500)
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
const baseInfo = ref([
|
||||||
|
{
|
||||||
|
title: '线索基本信息',
|
||||||
|
data: [
|
||||||
|
{ label: '线索提供者', value: '张三' },
|
||||||
|
{ label: '线索来源', value: '线下名单' },
|
||||||
|
{ label: '创建人', value: 'admin' },
|
||||||
|
{ label: '创建时间', value: '2025-02-12 11:30:00' },
|
||||||
|
{ label: '客户姓名', value: '韩梅梅' },
|
||||||
|
{ label: '联系电话', value: '18866668888' },
|
||||||
|
{
|
||||||
|
label: '基本情况',
|
||||||
|
value: '学生爸爸接电话,学生高三毕业,300多分,家长不清楚学生收到录取通知,家长说学生不读书了,我让家长先问问学生对未来的规划先和学生沟通一下,家长同意我们加他微信发专业资料给他看看,可以在微信上问问学生具体情况。推荐3+2,给家长发一下学校简介和专业资料。'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '电销信息',
|
||||||
|
data: [
|
||||||
|
{ label: '负责人', value: '张三' },
|
||||||
|
{ label: '所属组织', value: '广州团队-A组' },
|
||||||
|
{ label: '线索状态', value: '已添加' },
|
||||||
|
{ label: '跟进时间', value: '2025-02-12 11:30:00' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '招生信息',
|
||||||
|
data: [
|
||||||
|
{ label: '负责人', value: '张三' },
|
||||||
|
{ label: '所属组织', value: '广州团队-A组' },
|
||||||
|
{ label: '领取时间', value: '2025-02-12 11:19:00' },
|
||||||
|
{ label: '状态', value: '账号已添加' },
|
||||||
|
{ label: '是否转化成功', value: '' },
|
||||||
|
{ label: '备注', value: '' },
|
||||||
|
{ label: '成交时间', value: '' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
<style scoped></style>
|
|
@ -0,0 +1,83 @@
|
||||||
|
<template>
|
||||||
|
<el-timeline class="px-[6px]" v-loading="loading">
|
||||||
|
<el-timeline-item v-for="(item, index) in recordList" :key="index" type="primary" color="#0E66FB">
|
||||||
|
<el-space direction="vertical" alignment="normal">
|
||||||
|
<div class="text-primary">{{ item.date }}</div>
|
||||||
|
<div>
|
||||||
|
{{ item.user }}
|
||||||
|
<span class="text-black2">「{{ item.step }}」</span>
|
||||||
|
</div>
|
||||||
|
<div v-if="item.content" class="bg-primary-light-10 w-full p-[12px] rounded-[6px] flex flex-col gap-[6px]">
|
||||||
|
<span v-for="(value, key) in item.content" :key="key">{{ key }}:{{ value }}</span>
|
||||||
|
</div>
|
||||||
|
</el-space>
|
||||||
|
</el-timeline-item>
|
||||||
|
</el-timeline>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
default: 'clueRecord'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const loading = ref(false)
|
||||||
|
watch(
|
||||||
|
() => props.modelValue,
|
||||||
|
() => {
|
||||||
|
console.log('线索来源')
|
||||||
|
loading.value = true
|
||||||
|
setTimeout(() => {
|
||||||
|
loading.value = false
|
||||||
|
}, 500)
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
const recordList = ref([
|
||||||
|
{
|
||||||
|
date: '2025-02-12 15:47:00',
|
||||||
|
user: '电销老师:张三',
|
||||||
|
step: '添加跟进',
|
||||||
|
content: {
|
||||||
|
客户姓名: '韩梅梅',
|
||||||
|
联系电话: '188866668888',
|
||||||
|
基本情况:
|
||||||
|
'学生爸爸接电话,学生高三毕业,300多分,家长不清楚学生收到录取通知,家长说学生不读书了,我让家长先问问学生对未来的规划先和学生沟通一下,家长同意我们加他微信发专业资料给他看看,可以在微信上问问学生具体情况。推荐3'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ date: '2025-02-12 15:47:00', user: '招生老师:王五', step: '领取线索', content: null },
|
||||||
|
{
|
||||||
|
date: '2025-02-12 15:47:00',
|
||||||
|
user: '招生老师:王五',
|
||||||
|
step: '添加进展',
|
||||||
|
content: {
|
||||||
|
状态: '账号已添加'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-02-12 15:47:00',
|
||||||
|
user: '招生老师:王五',
|
||||||
|
step: '转化完成',
|
||||||
|
content: {
|
||||||
|
是否转化成功: '是',
|
||||||
|
备注: '已交部分定位金'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
<style scoped lang="scss">
|
||||||
|
:deep(.el-space) {
|
||||||
|
width: 100%;
|
||||||
|
.el-space__item {
|
||||||
|
&:last-child {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.el-timeline-item__tail) {
|
||||||
|
border-style: dashed;
|
||||||
|
border-color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,38 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<search-form v-model="queryParams" @reset-page="resetPage" @reset-params="resetParams" />
|
||||||
|
<clue-list :loading="pager.loading" :tableData="pager.lists">
|
||||||
|
<template #operation="{ row }">
|
||||||
|
<el-button type="primary" link @click="handleDetail(row)">详情</el-button>
|
||||||
|
</template>
|
||||||
|
</clue-list>
|
||||||
|
</div>
|
||||||
|
<clue-detail ref="clueDetailRef" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import searchForm from './modules/search-form.vue'
|
||||||
|
import clueList from './modules/clue-list.vue'
|
||||||
|
import clueDetail from './modules/clue-detail.vue'
|
||||||
|
import { postLists } from '@/api/org/post'
|
||||||
|
import { usePaging } from '@/hooks/usePaging'
|
||||||
|
|
||||||
|
const queryParams = reactive({
|
||||||
|
name: '',
|
||||||
|
conversionStatus: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const { pager, getLists, resetPage, resetParams } = usePaging({
|
||||||
|
fetchFun: postLists,
|
||||||
|
params: queryParams
|
||||||
|
})
|
||||||
|
getLists()
|
||||||
|
|
||||||
|
const clueDetailRef = ref()
|
||||||
|
const handleDetail = () => {
|
||||||
|
clueDetailRef.value.openDrawer({
|
||||||
|
title: '线索详情'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style scoped></style>
|
|
@ -0,0 +1,29 @@
|
||||||
|
<template>
|
||||||
|
<ProDrawer ref="proDrawerRef">
|
||||||
|
<el-tabs v-model="activeTab">
|
||||||
|
<el-tab-pane v-for="tab in tabs" :key="tab.name" :label="tab.label" :name="tab.name">
|
||||||
|
<component v-if="tab.name == activeTab" :is="tab.component" v-model="activeTab" />
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</ProDrawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import ProDrawer, { type IParams } from '@/components/ProDrawer/index.vue'
|
||||||
|
import baseIfno from '../components/clue-detail/base-info.vue'
|
||||||
|
import clueRecord from '../components/clue-detail/clue-record.vue'
|
||||||
|
|
||||||
|
const proDrawerRef = ref<InstanceType<typeof ProDrawer>>()
|
||||||
|
const activeTab = ref('baseInfo')
|
||||||
|
const tabs = shallowRef([
|
||||||
|
{ label: '基础信息', name: 'baseInfo', component: baseIfno },
|
||||||
|
{ label: '线索来源', name: 'clueRecord', component: clueRecord }
|
||||||
|
])
|
||||||
|
const openDrawer = (params: IParams) => {
|
||||||
|
proDrawerRef.value?.openDrawer(params)
|
||||||
|
}
|
||||||
|
defineExpose({
|
||||||
|
openDrawer
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<style scoped></style>
|
|
@ -0,0 +1,34 @@
|
||||||
|
<template>
|
||||||
|
<el-card shadow="never" class="!border-none mt-4">
|
||||||
|
<ProTable ref="proTableRef" :columns="columns" :tableData="tableData" :loading="loading" :maxHeight="530">
|
||||||
|
<template #operation="{ row }">
|
||||||
|
<slot name="operation" :row="row" />
|
||||||
|
</template>
|
||||||
|
</ProTable>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineProps({
|
||||||
|
loading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
tableData: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const proTableRef = ref()
|
||||||
|
const columns = reactive([
|
||||||
|
{ prop: 'accountName', label: '学生名字', width: 180 },
|
||||||
|
{ prop: 'mobile', label: '联系电话', width: 180 },
|
||||||
|
{ prop: 'organization', label: '电销老师', width: 180 },
|
||||||
|
{ prop: 'position', label: '转化老师', width: 180 },
|
||||||
|
{ prop: 'position', label: '名单来源', width: 180 },
|
||||||
|
{ prop: 'position', label: '转化情况', width: 180 },
|
||||||
|
{ prop: 'accountStatus', label: '创建人', width: 180 },
|
||||||
|
{ prop: 'operation', label: '操作', fixed: 'right', width: 250 }
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
<style scoped></style>
|
|
@ -0,0 +1,41 @@
|
||||||
|
<template>
|
||||||
|
<el-card shadow="never" class="!border-none">
|
||||||
|
<el-form ref="formRef" class="mb-[-16px]" :model="modelValue" :inline="true">
|
||||||
|
<el-form-item label="学生名字">
|
||||||
|
<el-input class="w-[280px]" placeholder="请输入" v-model="modelValue.name" clearable @keyup.enter="$emit('resetPage')" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="转化情况">
|
||||||
|
<el-select class="w-[280px]" v-model="modelValue.conversionStatus">
|
||||||
|
<el-option v-for="option in conversionOptions" :key="option.value" :label="option.label" :value="option.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="$emit('resetPage')">查询</el-button>
|
||||||
|
<el-button @click="$emit('resetParams')">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineProps({
|
||||||
|
modelValue: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
name: '',
|
||||||
|
conversionStatus: ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
defineEmits(['resetPage', 'resetParams'])
|
||||||
|
const conversionOptions = ref([
|
||||||
|
{ label: '有意向', value: 1 },
|
||||||
|
{ label: '待领取', value: 2 },
|
||||||
|
{ label: '转化中', value: 3 },
|
||||||
|
{ label: '已添加', value: 4 },
|
||||||
|
{ label: '异常待处理', value: 5 },
|
||||||
|
{ label: '已成交', value: 6 },
|
||||||
|
{ label: '已战败', value: 7 }
|
||||||
|
])
|
||||||
|
</script>
|
||||||
|
<style scoped></style>
|
|
@ -35,7 +35,8 @@ module.exports = {
|
||||||
'fill-light': 'var(--el-fill-color-light)',
|
'fill-light': 'var(--el-fill-color-light)',
|
||||||
'fill-lighter': 'var(--el-fill-color-lighter)',
|
'fill-lighter': 'var(--el-fill-color-lighter)',
|
||||||
mask: 'var(--el-mask-color)',
|
mask: 'var(--el-mask-color)',
|
||||||
green: 'var(--color-green)'
|
green: 'var(--color-green)',
|
||||||
|
black2: 'var(--el-text-color-black2)'
|
||||||
},
|
},
|
||||||
fontFamily: {
|
fontFamily: {
|
||||||
sans: ['PingFang SC', 'Arial', 'Hiragino Sans GB', 'Microsoft YaHei', 'sans-serif']
|
sans: ['PingFang SC', 'Arial', 'Hiragino Sans GB', 'Microsoft YaHei', 'sans-serif']
|
||||||
|
|
Loading…
Reference in New Issue