Browse Source

feat(zhjw): 添加销售管理功能

- 新增销售管理列表和详情页面
- 实现销售管理的添加、编辑和删除功能
- 添加相关 API 接口和语言包
master
liutong 1 year ago
parent
commit
d1d542fa1f
  1. 58
      admin/src/addon/zhjw/api/sales.ts
  2. 45
      admin/src/addon/zhjw/lang/zh-cn/sales.sales.json
  3. 39
      admin/src/addon/zhjw/lang/zh-cn/sales.sales_edit.json
  4. 417
      admin/src/addon/zhjw/views/sales/sales.vue
  5. 421
      admin/src/addon/zhjw/views/sales/sales_edit.vue
  6. 62
      niucloud/addon/zhjw/admin/api/sales.ts
  7. 45
      niucloud/addon/zhjw/admin/lang/zh-cn/sales.sales.json
  8. 39
      niucloud/addon/zhjw/admin/lang/zh-cn/sales.sales_edit.json
  9. 414
      niucloud/addon/zhjw/admin/views/sales/sales.vue
  10. 418
      niucloud/addon/zhjw/admin/views/sales/sales_edit.vue
  11. 142
      niucloud/addon/zhjw/app/adminapi/controller/sales/Sales.php
  12. 26
      niucloud/addon/zhjw/app/adminapi/route/route.php
  13. 295
      niucloud/addon/zhjw/app/model/sales/Sales.php
  14. 112
      niucloud/addon/zhjw/app/service/admin/sales/SalesService.php
  15. 52
      niucloud/addon/zhjw/app/validate/sales/Sales.php

58
admin/src/addon/zhjw/api/sales.ts

@ -0,0 +1,58 @@
import request from '@/utils/request'
// USER_CODE_BEGIN -- zhjw_sales
/**
*
* @param params
* @returns
*/
export function getSalesList(params: Record<string, any>) {
return request.get(`zhjw/sales`, {params})
}
/**
*
* @param id id
* @returns
*/
export function getSalesInfo(id: number) {
return request.get(`zhjw/sales/${id}`);
}
/**
*
* @param params
* @returns
*/
export function addSales(params: Record<string, any>) {
return request.post('zhjw/sales', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param id
* @param params
* @returns
*/
export function editSales(params: Record<string, any>) {
return request.put(`zhjw/sales/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param id
* @returns
*/
export function deleteSales(id: number) {
return request.delete(`zhjw/sales/${id}`, { showErrorMessage: true, showSuccessMessage: true })
}
export function getWithStaffList(params: Record<string, any>) {
return request.get('zhjw/staff_all', {params})
}
export function getWithSysAreaList(params: Record<string, any>) {
return request.get('zhjw/sys_area_all', {params})
}
// USER_CODE_END -- zhjw_sales

45
admin/src/addon/zhjw/lang/zh-cn/sales.sales.json

@ -0,0 +1,45 @@
{
"id":"序号",
"studentPhone":"学生手机号",
"studentPhonePlaceholder":"请输入学生手机号",
"studentName":"学生姓名",
"studentNamePlaceholder":"请输入学生姓名",
"sex":"性别",
"sexPlaceholder":"请输入性别",
"age":"年龄",
"agePlaceholder":"请输入年龄",
"schoolName":"学校名称",
"schoolNamePlaceholder":"请输入学校名称",
"grade":"年级",
"gradePlaceholder":"请输入年级",
"className":"班级名称",
"classNamePlaceholder":"请输入班级名称",
"sourceChannel":"来源渠道",
"sourceChannelPlaceholder":"请输入来源渠道",
"customerSource":"客户来源",
"customerSourcePlaceholder":"请输入客户来源",
"addStaffId":"添加这条数据的工作人员",
"addStaffIdPlaceholder":"全部",
"getStaffId":"领取这条客户数据的工作人员",
"getStaffIdPlaceholder":"全部",
"contactName":"联系人姓名",
"contactNamePlaceholder":"请输入联系人姓名",
"provinceId":"所在地-省",
"provinceIdPlaceholder":"全部",
"cityId":"所在地-市",
"cityIdPlaceholder":"全部",
"districtId":"所在地-区",
"districtIdPlaceholder":"全部",
"communityName":"小区名称",
"communityNamePlaceholder":"请输入小区名称",
"customerTags":"客户标签",
"customerTagsPlaceholder":"请输入客户标签",
"createTime":"添加时间",
"createTimePlaceholder":"请输入添加时间",
"updateTime":"更新时间",
"addSales":"添加销售管理",
"updateSales":"编辑销售管理",
"salesDeleteTips":"确定要删除该数据吗?",
"startDate":"请选择开始时间",
"endDate":"请选择结束时间"
}

39
admin/src/addon/zhjw/lang/zh-cn/sales.sales_edit.json

@ -0,0 +1,39 @@
{
"studentPhone":"学生手机号",
"studentName":"学生姓名",
"sex":"性别",
"age":"年龄",
"schoolName":"学校名称",
"grade":"年级",
"className":"班级名称",
"sourceChannel":"来源渠道",
"customerSource":"客户来源",
"addStaffId":"添加这条数据的工作人员",
"getStaffId":"领取这条客户数据的工作人员",
"contactName":"联系人姓名",
"provinceId":"所在地-省",
"cityId":"所在地-市",
"districtId":"所在地-区",
"communityName":"小区名称",
"customerTags":"客户标签",
"studentPhonePlaceholder":"请输入学生手机号",
"studentNamePlaceholder":"请输入学生姓名",
"sexPlaceholder":"请选择性别",
"agePlaceholder":"请输入年龄",
"schoolNamePlaceholder":"请输入学校名称",
"gradePlaceholder":"请输入年级",
"classNamePlaceholder":"请输入班级名称",
"sourceChannelPlaceholder":"请选择来源渠道",
"customerSourcePlaceholder":"请选择客户来源",
"addStaffIdPlaceholder":"请选择添加这条数据的工作人员",
"getStaffIdPlaceholder":"请选择领取这条客户数据的工作人员",
"contactNamePlaceholder":"请输入联系人姓名",
"provinceIdPlaceholder":"请选择所在地-省",
"cityIdPlaceholder":"请选择所在地-市",
"districtIdPlaceholder":"请选择所在地-区",
"communityNamePlaceholder":"请输入小区名称",
"customerTagsPlaceholder":"请选择客户标签",
"addSales":"添加销售管理",
"updateSales":"编辑销售管理",
"salesDeleteTips":"确定要删除该销售管理吗?"
}

417
admin/src/addon/zhjw/views/sales/sales.vue

@ -0,0 +1,417 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
<span class="text-lg">{{pageName}}</span>
<el-button type="primary" @click="addEvent">
{{ t('addSales') }}
</el-button>
</div>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="salesTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('studentPhone')" prop="student_phone">
<el-input v-model="salesTable.searchParam.student_phone" :placeholder="t('studentPhonePlaceholder')" />
</el-form-item>
<el-form-item :label="t('studentName')" prop="student_name">
<el-input v-model="salesTable.searchParam.student_name" :placeholder="t('studentNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('sex')" prop="sex">
<el-select class="w-[280px]" v-model="salesTable.searchParam.sex" clearable :placeholder="t('sexPlaceholder')">
<el-option label="全部" value=""></el-option>
<el-option
v-for="(item, index) in sexList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('age')" prop="age">
<range-input v-model="salesTable.searchParam.age"/>
</el-form-item>
<el-form-item :label="t('schoolName')" prop="school_name">
<el-input v-model="salesTable.searchParam.school_name" :placeholder="t('schoolNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('grade')" prop="grade">
<el-input v-model="salesTable.searchParam.grade" :placeholder="t('gradePlaceholder')" />
</el-form-item>
<el-form-item :label="t('className')" prop="class_name">
<el-input v-model="salesTable.searchParam.class_name" :placeholder="t('classNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('sourceChannel')" prop="source_channel">
<el-select class="w-[280px]" v-model="salesTable.searchParam.source_channel" clearable :placeholder="t('sourceChannelPlaceholder')">
<el-option label="全部" value=""></el-option>
<el-option
v-for="(item, index) in source_channelList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('customerSource')" prop="customer_source">
<el-select class="w-[280px]" v-model="salesTable.searchParam.customer_source" clearable :placeholder="t('customerSourcePlaceholder')">
<el-option label="全部" value=""></el-option>
<el-option
v-for="(item, index) in customer_sourceList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('addStaffId')" prop="add_staff_id">
<el-select class="w-[280px]" v-model="salesTable.searchParam.add_staff_id" clearable :placeholder="t('addStaffIdPlaceholder')">
<el-option
v-for="(item, index) in addStaffIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('getStaffId')" prop="get_staff_id">
<el-select class="w-[280px]" v-model="salesTable.searchParam.get_staff_id" clearable :placeholder="t('getStaffIdPlaceholder')">
<el-option
v-for="(item, index) in getStaffIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('contactName')" prop="contact_name">
<el-input v-model="salesTable.searchParam.contact_name" :placeholder="t('contactNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('provinceId')" prop="province_id">
<el-select class="w-[280px]" v-model="salesTable.searchParam.province_id" clearable :placeholder="t('provinceIdPlaceholder')">
<el-option
v-for="(item, index) in provinceIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('cityId')" prop="city_id">
<el-select class="w-[280px]" v-model="salesTable.searchParam.city_id" clearable :placeholder="t('cityIdPlaceholder')">
<el-option
v-for="(item, index) in cityIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('districtId')" prop="district_id">
<el-select class="w-[280px]" v-model="salesTable.searchParam.district_id" clearable :placeholder="t('districtIdPlaceholder')">
<el-option
v-for="(item, index) in districtIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('communityName')" prop="community_name">
<el-input v-model="salesTable.searchParam.community_name" :placeholder="t('communityNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('createTime')" prop="create_time">
<el-date-picker v-model="salesTable.searchParam.create_time" type="datetimerange" format="YYYY-MM-DD hh:mm:ss"
:start-placeholder="t('startDate')" :end-placeholder="t('endDate')" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadSalesList()">{{ t('search') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="mt-[10px]">
<el-table :data="salesTable.data" size="large" v-loading="salesTable.loading">
<template #empty>
<span>{{ !salesTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="id" :label="t('id')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="student_phone" :label="t('studentPhone')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="student_name" :label="t('studentName')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('sex')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in sexList">
<div v-if="item.value == row.sex">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column prop="age" :label="t('age')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="school_name" :label="t('schoolName')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="grade" :label="t('grade')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="class_name" :label="t('className')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('sourceChannel')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in source_channelList">
<div v-if="item.value == row.source_channel">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column :label="t('customerSource')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in customer_sourceList">
<div v-if="item.value == row.customer_source">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column prop="add_staff_id_name" :label="t('addStaffId')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="get_staff_id_name" :label="t('getStaffId')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="contact_name" :label="t('contactName')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="province_id_name" :label="t('provinceId')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="city_id_name" :label="t('cityId')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="district_id_name" :label="t('districtId')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="community_name" :label="t('communityName')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('customerTags')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in customer_tagsList">
<div v-if="item.value == row.customer_tags">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column :label="t('createTime')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.create_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('updateTime')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.update_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('operation')" fixed="right" min-width="120">
<template #default="{ row }">
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="salesTable.page" v-model:page-size="salesTable.limit"
layout="total, sizes, prev, pager, next, jumper" :total="salesTable.total"
@size-change="loadSalesList()" @current-change="loadSalesList" />
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import { t } from '@/lang'
import { useDictionary } from '@/app/api/dict'
import {getSalesList, deleteSales, getWithStaffList, getWithSysAreaList} from '@/addon/zhjw/api/sales'
import { img } from '@/utils/common'
import { ElMessageBox,FormInstance } from 'element-plus'
import { useRouter } from 'vue-router'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title;
let salesTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam:{
"student_phone":"",
"student_name":"",
"sex":"",
"age":[],
"school_name":"",
"grade":"",
"class_name":"",
"source_channel":"",
"customer_source":"",
"add_staff_id":"",
"get_staff_id":"",
"contact_name":"",
"province_id":"",
"city_id":"",
"district_id":"",
"community_name":"",
"customer_tags":"",
"create_time":""
}
})
const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
const sexList = ref([] as any[])
const sexDictList = async () => {
sexList.value = await (await useDictionary('users_sex')).data.dictionary
}
sexDictList();
const source_channelList = ref([] as any[])
const source_channelDictList = async () => {
source_channelList.value = await (await useDictionary('source_channel')).data.dictionary
}
source_channelDictList();
const customer_sourceList = ref([] as any[])
const customer_sourceDictList = async () => {
customer_sourceList.value = await (await useDictionary('customer_source')).data.dictionary
}
customer_sourceDictList();
const customer_tagsList = ref([] as any[])
const customer_tagsDictList = async () => {
customer_tagsList.value = await (await useDictionary('customer_tags')).data.dictionary
}
customer_tagsDictList();
/**
* 获取销售管理列表
*/
const loadSalesList = (page: number = 1) => {
salesTable.loading = true
salesTable.page = page
getSalesList({
page: salesTable.page,
limit: salesTable.limit,
...salesTable.searchParam
}).then(res => {
salesTable.loading = false
salesTable.data = res.data.data
salesTable.total = res.data.total
}).catch(() => {
salesTable.loading = false
})
}
loadSalesList()
const router = useRouter()
/**
* 添加销售管理
*/
const addEvent = () => {
router.push('/sales/sales_edit')
}
/**
* 编辑销售管理
* @param data
*/
const editEvent = (data: any) => {
router.push('/sales/sales_edit?id='+data.id)
}
/**
* 删除销售管理
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('salesDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
deleteSales(id).then(() => {
loadSalesList()
}).catch(() => {
})
})
}
const addStaffIdList = ref([])
const setAddStaffIdList = async () => {
addStaffIdList.value = await (await getWithStaffList({})).data
}
setAddStaffIdList()
const getStaffIdList = ref([])
const setGetStaffIdList = async () => {
getStaffIdList.value = await (await getWithStaffList({})).data
}
setGetStaffIdList()
const provinceIdList = ref([])
const setProvinceIdList = async () => {
provinceIdList.value = await (await getWithSysAreaList({})).data
}
setProvinceIdList()
const cityIdList = ref([])
const setCityIdList = async () => {
cityIdList.value = await (await getWithSysAreaList({})).data
}
setCityIdList()
const districtIdList = ref([])
const setDistrictIdList = async () => {
districtIdList.value = await (await getWithSysAreaList({})).data
}
setDistrictIdList()
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadSalesList()
}
</script>
<style lang="scss" scoped>
/* 多行超出隐藏 */
.multi-hidden {
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>

421
admin/src/addon/zhjw/views/sales/sales_edit.vue

@ -0,0 +1,421 @@
<template>
<div class="main-container">
<div class="detail-head">
<div class="left" @click="back()">
<span class="iconfont iconxiangzuojiantou !text-xs"></span>
<span class="ml-[1px]">{{t('returnToPreviousPage')}}</span>
</div>
<span class="adorn">|</span>
<span class="right">{{ pageName }}</span>
</div>
<el-card class="box-card !border-none" shadow="never">
<el-form :model="formData" label-width="90px" ref="formRef" :rules="formRules" class="page-form">
<el-form-item :label="t('studentPhone')" prop="student_phone">
<el-input v-model="formData.student_phone" clearable :placeholder="t('studentPhonePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('studentName')" prop="student_name">
<el-input v-model="formData.student_name" clearable :placeholder="t('studentNamePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('sex')" prop="sex">
<el-select class="input-width" v-model="formData.sex" clearable :placeholder="t('sexPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in sexList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('age')" prop="age">
<el-input-number v-model="formData.age" clearable :placeholder="t('agePlaceholder')" class="input-width" :min = "0" max = "300" />
</el-form-item>
<el-form-item :label="t('schoolName')" prop="school_name">
<el-input v-model="formData.school_name" clearable :placeholder="t('schoolNamePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('grade')" >
<el-input v-model="formData.grade" clearable :placeholder="t('gradePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('className')" >
<el-input v-model="formData.class_name" clearable :placeholder="t('classNamePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('sourceChannel')" prop="source_channel">
<el-select class="input-width" v-model="formData.source_channel" clearable :placeholder="t('sourceChannelPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in source_channelList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('customerSource')" prop="customer_source">
<el-select class="input-width" v-model="formData.customer_source" clearable :placeholder="t('customerSourcePlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in customer_sourceList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('addStaffId')" prop="add_staff_id">
<el-select class="input-width" v-model="formData.add_staff_id" clearable :placeholder="t('addStaffIdPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in addStaffIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('getStaffId')" >
<el-select class="input-width" v-model="formData.get_staff_id" clearable :placeholder="t('getStaffIdPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in getStaffIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('contactName')" prop="contact_name">
<el-input v-model="formData.contact_name" clearable :placeholder="t('contactNamePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('provinceId')" >
<el-select class="input-width" v-model="formData.province_id" clearable :placeholder="t('provinceIdPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in provinceIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('cityId')" >
<el-select class="input-width" v-model="formData.city_id" clearable :placeholder="t('cityIdPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in cityIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('districtId')" >
<el-select class="input-width" v-model="formData.district_id" clearable :placeholder="t('districtIdPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in districtIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('communityName')" >
<el-input v-model="formData.community_name" clearable :placeholder="t('communityNamePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('customerTags')" >
<el-checkbox-group v-model="formData.customer_tags" :placeholder="t('customerTagsPlaceholder')">
<el-checkbox
v-for="(item, index) in customer_tagsList"
:key="index"
:label="item.value">
{{ item.name }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-form>
</el-card>
<div class="fixed-footer-wrap">
<div class="fixed-footer">
<el-button type="primary" @click="onSave(formRef)">{{ t('save') }}</el-button>
<el-button @click="back()">{{ t('cancel') }}</el-button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, watch } from 'vue'
import { t } from '@/lang'
import { useDictionary } from '@/app/api/dict'
import type { FormInstance } from 'element-plus'
import { getSalesInfo,addSales,editSales, getWithStaffList, getWithSysAreaList } from '@/addon/zhjw/api/sales';
import { useRoute } from 'vue-router'
const route = useRoute()
const id:number = parseInt(route.query.id);
const loading = ref(false)
const pageName = route.meta.title
/**
* 表单数据
*/
const initialFormData = {
id: 0,
student_phone: '',
student_name: '',
sex: '',
age: '',
school_name: '',
grade: '',
class_name: '',
source_channel: '',
customer_source: '',
add_staff_id: '',
get_staff_id: '',
contact_name: '',
province_id: '',
city_id: '',
district_id: '',
community_name: '',
customer_tags: '',
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const setFormData = async (id:number = 0) => {
Object.assign(formData, initialFormData)
const data = await (await getSalesInfo(id)).data
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
if(id) setFormData(id);
const formRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
let sexList = ref([])
const sexDictList = async () => {
sexList.value = await (await useDictionary('users_sex')).data.dictionary
}
sexDictList();
watch(() => sexList.value, () => { formData.sex = sexList.value[0].value })
let source_channelList = ref([])
const source_channelDictList = async () => {
source_channelList.value = await (await useDictionary('source_channel')).data.dictionary
}
source_channelDictList();
watch(() => source_channelList.value, () => { formData.source_channel = source_channelList.value[0].value })
let customer_sourceList = ref([])
const customer_sourceDictList = async () => {
customer_sourceList.value = await (await useDictionary('customer_source')).data.dictionary
}
customer_sourceDictList();
watch(() => customer_sourceList.value, () => { formData.customer_source = customer_sourceList.value[0].value })
let customer_tagsList = ref([])
const customer_tagsDictList = async () => {
customer_tagsList.value = await (await useDictionary('customer_tags')).data.dictionary
}
customer_tagsDictList();
const addStaffIdList = ref([] as any[])
const setAddStaffIdList = async () => {
addStaffIdList.value = await (await getWithStaffList({})).data
}
setAddStaffIdList()
const getStaffIdList = ref([] as any[])
const setGetStaffIdList = async () => {
getStaffIdList.value = await (await getWithStaffList({})).data
}
setGetStaffIdList()
const provinceIdList = ref([] as any[])
const setProvinceIdList = async () => {
provinceIdList.value = await (await getWithSysAreaList({})).data
}
setProvinceIdList()
const cityIdList = ref([] as any[])
const setCityIdList = async () => {
cityIdList.value = await (await getWithSysAreaList({})).data
}
setCityIdList()
const districtIdList = ref([] as any[])
const setDistrictIdList = async () => {
districtIdList.value = await (await getWithSysAreaList({})).data
}
setDistrictIdList()
//
const formRules = computed(() => {
return {
student_phone: [
{ required: true, message: t('studentPhonePlaceholder'), trigger: 'blur' },
]
,
student_name: [
{ required: true, message: t('studentNamePlaceholder'), trigger: 'blur' },
]
,
sex: [
{ required: true, message: t('sexPlaceholder'), trigger: 'blur' },
]
,
age: [
{ required: true, message: t('agePlaceholder'), trigger: 'blur' },
{ validator: (rule: any, value: string, callback: any) => { if (value && !/^\d{0,300}$/.test(value)) { callback(new Error(t('generateBetween')))} else { callback() }}},
]
,
school_name: [
{ required: true, message: t('schoolNamePlaceholder'), trigger: 'blur' },
]
,
grade: [
{ required: true, message: t('gradePlaceholder'), trigger: 'blur' },
]
,
class_name: [
{ required: true, message: t('classNamePlaceholder'), trigger: 'blur' },
]
,
source_channel: [
{ required: true, message: t('sourceChannelPlaceholder'), trigger: 'blur' },
]
,
customer_source: [
{ required: true, message: t('customerSourcePlaceholder'), trigger: 'blur' },
]
,
add_staff_id: [
{ required: true, message: t('addStaffIdPlaceholder'), trigger: 'blur' },
]
,
get_staff_id: [
{ required: true, message: t('getStaffIdPlaceholder'), trigger: 'blur' },
]
,
contact_name: [
{ required: true, message: t('contactNamePlaceholder'), trigger: 'blur' },
]
,
province_id: [
{ required: true, message: t('provinceIdPlaceholder'), trigger: 'blur' },
]
,
city_id: [
{ required: true, message: t('cityIdPlaceholder'), trigger: 'blur' },
]
,
district_id: [
{ required: true, message: t('districtIdPlaceholder'), trigger: 'blur' },
]
,
community_name: [
{ required: true, message: t('communityNamePlaceholder'), trigger: 'blur' },
]
,
customer_tags: [
{ required: true, message: t('customerTagsPlaceholder'), trigger: 'blur' },
]
,
}
})
const onSave = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
const save = id ? editSales : addSales
save(data).then(res => {
loading.value = false
history.back()
}).catch(err => {
loading.value = false
})
}
})
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
const back = () => {
history.back()
}
</script>
<style lang="scss" scoped></style>

62
niucloud/addon/zhjw/admin/api/sales.ts

@ -0,0 +1,62 @@
import request from '@/utils/request'
// USER_CODE_BEGIN -- zhjw_sales
/**
*
* @param params
* @returns
*/
export function getSalesList(params: Record<string, any>) {
return request.get(`zhjw/sales`, {params})
}
/**
*
* @param id id
* @returns
*/
export function getSalesInfo(id: number) {
return request.get(`zhjw/sales/${id}`);
}
/**
*
* @param params
* @returns
*/
export function addSales(params: Record<string, any>) {
return request.post('zhjw/sales', params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param id
* @param params
* @returns
*/
export function editSales(params: Record<string, any>) {
return request.put(`zhjw/sales/${params.id}`, params, { showErrorMessage: true, showSuccessMessage: true })
}
/**
*
* @param id
* @returns
*/
export function deleteSales(id: number) {
return request.delete(`zhjw/sales/${id}`, { showErrorMessage: true, showSuccessMessage: true })
}
export function getWithStaffList(params: Record<string,any>){
return request.get('zhjw/staff_all', {params})
}export function getWithStaffList(params: Record<string,any>){
return request.get('zhjw/staff_all', {params})
}export function getWithSysAreaList(params: Record<string,any>){
return request.get('zhjw/sys_area_all', {params})
}export function getWithSysAreaList(params: Record<string,any>){
return request.get('zhjw/sys_area_all', {params})
}export function getWithSysAreaList(params: Record<string,any>){
return request.get('zhjw/sys_area_all', {params})
}
// USER_CODE_END -- zhjw_sales

45
niucloud/addon/zhjw/admin/lang/zh-cn/sales.sales.json

@ -0,0 +1,45 @@
{
"id":"序号",
"studentPhone":"学生手机号",
"studentPhonePlaceholder":"请输入学生手机号",
"studentName":"学生姓名",
"studentNamePlaceholder":"请输入学生姓名",
"sex":"性别",
"sexPlaceholder":"请输入性别",
"age":"年龄",
"agePlaceholder":"请输入年龄",
"schoolName":"学校名称",
"schoolNamePlaceholder":"请输入学校名称",
"grade":"年级",
"gradePlaceholder":"请输入年级",
"className":"班级名称",
"classNamePlaceholder":"请输入班级名称",
"sourceChannel":"来源渠道",
"sourceChannelPlaceholder":"请输入来源渠道",
"customerSource":"客户来源",
"customerSourcePlaceholder":"请输入客户来源",
"addStaffId":"添加这条数据的工作人员",
"addStaffIdPlaceholder":"全部",
"getStaffId":"领取这条客户数据的工作人员",
"getStaffIdPlaceholder":"全部",
"contactName":"联系人姓名",
"contactNamePlaceholder":"请输入联系人姓名",
"provinceId":"所在地-省",
"provinceIdPlaceholder":"全部",
"cityId":"所在地-市",
"cityIdPlaceholder":"全部",
"districtId":"所在地-区",
"districtIdPlaceholder":"全部",
"communityName":"小区名称",
"communityNamePlaceholder":"请输入小区名称",
"customerTags":"客户标签",
"customerTagsPlaceholder":"请输入客户标签",
"createTime":"添加时间",
"createTimePlaceholder":"请输入添加时间",
"updateTime":"更新时间",
"addSales":"添加销售管理",
"updateSales":"编辑销售管理",
"salesDeleteTips":"确定要删除该数据吗?",
"startDate":"请选择开始时间",
"endDate":"请选择结束时间"
}

39
niucloud/addon/zhjw/admin/lang/zh-cn/sales.sales_edit.json

@ -0,0 +1,39 @@
{
"studentPhone":"学生手机号",
"studentName":"学生姓名",
"sex":"性别",
"age":"年龄",
"schoolName":"学校名称",
"grade":"年级",
"className":"班级名称",
"sourceChannel":"来源渠道",
"customerSource":"客户来源",
"addStaffId":"添加这条数据的工作人员",
"getStaffId":"领取这条客户数据的工作人员",
"contactName":"联系人姓名",
"provinceId":"所在地-省",
"cityId":"所在地-市",
"districtId":"所在地-区",
"communityName":"小区名称",
"customerTags":"客户标签",
"studentPhonePlaceholder":"请输入学生手机号",
"studentNamePlaceholder":"请输入学生姓名",
"sexPlaceholder":"请选择性别",
"agePlaceholder":"请输入年龄",
"schoolNamePlaceholder":"请输入学校名称",
"gradePlaceholder":"请输入年级",
"classNamePlaceholder":"请输入班级名称",
"sourceChannelPlaceholder":"请选择来源渠道",
"customerSourcePlaceholder":"请选择客户来源",
"addStaffIdPlaceholder":"请选择添加这条数据的工作人员",
"getStaffIdPlaceholder":"请选择领取这条客户数据的工作人员",
"contactNamePlaceholder":"请输入联系人姓名",
"provinceIdPlaceholder":"请选择所在地-省",
"cityIdPlaceholder":"请选择所在地-市",
"districtIdPlaceholder":"请选择所在地-区",
"communityNamePlaceholder":"请输入小区名称",
"customerTagsPlaceholder":"请选择客户标签",
"addSales":"添加销售管理",
"updateSales":"编辑销售管理",
"salesDeleteTips":"确定要删除该销售管理吗?"
}

414
niucloud/addon/zhjw/admin/views/sales/sales.vue

@ -0,0 +1,414 @@
<template>
<div class="main-container">
<el-card class="box-card !border-none" shadow="never">
<div class="flex justify-between items-center">
<span class="text-lg">{{pageName}}</span>
<el-button type="primary" @click="addEvent">
{{ t('addSales') }}
</el-button>
</div>
<el-card class="box-card !border-none my-[10px] table-search-wrap" shadow="never">
<el-form :inline="true" :model="salesTable.searchParam" ref="searchFormRef">
<el-form-item :label="t('studentPhone')" prop="student_phone">
<el-input v-model="salesTable.searchParam.student_phone" :placeholder="t('studentPhonePlaceholder')" />
</el-form-item>
<el-form-item :label="t('studentName')" prop="student_name">
<el-input v-model="salesTable.searchParam.student_name" :placeholder="t('studentNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('sex')" prop="sex">
<el-select class="w-[280px]" v-model="salesTable.searchParam.sex" clearable :placeholder="t('sexPlaceholder')">
<el-option label="全部" value=""></el-option>
<el-option
v-for="(item, index) in sexList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('age')" prop="age">
<range-input v-model="salesTable.searchParam.age"/>
</el-form-item>
<el-form-item :label="t('schoolName')" prop="school_name">
<el-input v-model="salesTable.searchParam.school_name" :placeholder="t('schoolNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('grade')" prop="grade">
<el-input v-model="salesTable.searchParam.grade" :placeholder="t('gradePlaceholder')" />
</el-form-item>
<el-form-item :label="t('className')" prop="class_name">
<el-input v-model="salesTable.searchParam.class_name" :placeholder="t('classNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('sourceChannel')" prop="source_channel">
<el-select class="w-[280px]" v-model="salesTable.searchParam.source_channel" clearable :placeholder="t('sourceChannelPlaceholder')">
<el-option label="全部" value=""></el-option>
<el-option
v-for="(item, index) in source_channelList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('customerSource')" prop="customer_source">
<el-select class="w-[280px]" v-model="salesTable.searchParam.customer_source" clearable :placeholder="t('customerSourcePlaceholder')">
<el-option label="全部" value=""></el-option>
<el-option
v-for="(item, index) in customer_sourceList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('addStaffId')" prop="add_staff_id">
<el-select class="w-[280px]" v-model="salesTable.searchParam.add_staff_id" clearable :placeholder="t('addStaffIdPlaceholder')">
<el-option
v-for="(item, index) in addStaffIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('getStaffId')" prop="get_staff_id">
<el-select class="w-[280px]" v-model="salesTable.searchParam.get_staff_id" clearable :placeholder="t('getStaffIdPlaceholder')">
<el-option
v-for="(item, index) in getStaffIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('contactName')" prop="contact_name">
<el-input v-model="salesTable.searchParam.contact_name" :placeholder="t('contactNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('provinceId')" prop="province_id">
<el-select class="w-[280px]" v-model="salesTable.searchParam.province_id" clearable :placeholder="t('provinceIdPlaceholder')">
<el-option
v-for="(item, index) in provinceIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('cityId')" prop="city_id">
<el-select class="w-[280px]" v-model="salesTable.searchParam.city_id" clearable :placeholder="t('cityIdPlaceholder')">
<el-option
v-for="(item, index) in cityIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('districtId')" prop="district_id">
<el-select class="w-[280px]" v-model="salesTable.searchParam.district_id" clearable :placeholder="t('districtIdPlaceholder')">
<el-option
v-for="(item, index) in districtIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('communityName')" prop="community_name">
<el-input v-model="salesTable.searchParam.community_name" :placeholder="t('communityNamePlaceholder')" />
</el-form-item>
<el-form-item :label="t('createTime')" prop="create_time">
<el-date-picker v-model="salesTable.searchParam.create_time" type="datetimerange" format="YYYY-MM-DD hh:mm:ss"
:start-placeholder="t('startDate')" :end-placeholder="t('endDate')" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="loadSalesList()">{{ t('search') }}</el-button>
<el-button @click="resetForm(searchFormRef)">{{ t('reset') }}</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="mt-[10px]">
<el-table :data="salesTable.data" size="large" v-loading="salesTable.loading">
<template #empty>
<span>{{ !salesTable.loading ? t('emptyData') : '' }}</span>
</template>
<el-table-column prop="id" :label="t('id')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="student_phone" :label="t('studentPhone')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="student_name" :label="t('studentName')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('sex')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in sexList">
<div v-if="item.value == row.sex">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column prop="age" :label="t('age')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="school_name" :label="t('schoolName')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="grade" :label="t('grade')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="class_name" :label="t('className')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('sourceChannel')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in source_channelList">
<div v-if="item.value == row.source_channel">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column :label="t('customerSource')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in customer_sourceList">
<div v-if="item.value == row.customer_source">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column prop="add_staff_id_name" :label="t('addStaffId')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="get_staff_id_name" :label="t('getStaffId')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="contact_name" :label="t('contactName')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="province_id_name" :label="t('provinceId')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="city_id_name" :label="t('cityId')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="district_id_name" :label="t('districtId')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column prop="community_name" :label="t('communityName')" min-width="120" :show-overflow-tooltip="true"/>
<el-table-column :label="t('customerTags')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
<div v-for="(item, index) in customer_tagsList">
<div v-if="item.value == row.customer_tags">{{ item.name }}</div>
</div>
</template>
</el-table-column>
<el-table-column :label="t('createTime')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.create_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('updateTime')" min-width="180" align="center" :show-overflow-tooltip="true">
<template #default="{ row }">
{{ row.update_time || '' }}
</template>
</el-table-column>
<el-table-column :label="t('operation')" fixed="right" min-width="120">
<template #default="{ row }">
<el-button type="primary" link @click="editEvent(row)">{{ t('edit') }}</el-button>
<el-button type="primary" link @click="deleteEvent(row.id)">{{ t('delete') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="mt-[16px] flex justify-end">
<el-pagination v-model:current-page="salesTable.page" v-model:page-size="salesTable.limit"
layout="total, sizes, prev, pager, next, jumper" :total="salesTable.total"
@size-change="loadSalesList()" @current-change="loadSalesList" />
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref, watch } from 'vue'
import { t } from '@/lang'
import { useDictionary } from '@/app/api/dict'
import { getSalesList, deleteSales, getWithStaffList, getWithStaffList, getWithSysAreaList, getWithSysAreaList, getWithSysAreaList } from '@/addon/zhjw/api/sales'
import { img } from '@/utils/common'
import { ElMessageBox,FormInstance } from 'element-plus'
import { useRouter } from 'vue-router'
import { useRoute } from 'vue-router'
const route = useRoute()
const pageName = route.meta.title;
let salesTable = reactive({
page: 1,
limit: 10,
total: 0,
loading: true,
data: [],
searchParam:{
"student_phone":"",
"student_name":"",
"sex":"",
"age":[],
"school_name":"",
"grade":"",
"class_name":"",
"source_channel":"",
"customer_source":"",
"add_staff_id":"",
"get_staff_id":"",
"contact_name":"",
"province_id":"",
"city_id":"",
"district_id":"",
"community_name":"",
"customer_tags":"",
"create_time":""
}
})
const searchFormRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
const sexList = ref([] as any[])
const sexDictList = async () => {
sexList.value = await (await useDictionary('users_sex')).data.dictionary
}
sexDictList();
const source_channelList = ref([] as any[])
const source_channelDictList = async () => {
source_channelList.value = await (await useDictionary('source_channel')).data.dictionary
}
source_channelDictList();
const customer_sourceList = ref([] as any[])
const customer_sourceDictList = async () => {
customer_sourceList.value = await (await useDictionary('customer_source')).data.dictionary
}
customer_sourceDictList();
const customer_tagsList = ref([] as any[])
const customer_tagsDictList = async () => {
customer_tagsList.value = await (await useDictionary('customer_tags')).data.dictionary
}
customer_tagsDictList();
/**
* 获取销售管理列表
*/
const loadSalesList = (page: number = 1) => {
salesTable.loading = true
salesTable.page = page
getSalesList({
page: salesTable.page,
limit: salesTable.limit,
...salesTable.searchParam
}).then(res => {
salesTable.loading = false
salesTable.data = res.data.data
salesTable.total = res.data.total
}).catch(() => {
salesTable.loading = false
})
}
loadSalesList()
const router = useRouter()
/**
* 添加销售管理
*/
const addEvent = () => {
router.push('/sales/sales_edit')
}
/**
* 编辑销售管理
* @param data
*/
const editEvent = (data: any) => {
router.push('/sales/sales_edit?id='+data.id)
}
/**
* 删除销售管理
*/
const deleteEvent = (id: number) => {
ElMessageBox.confirm(t('salesDeleteTips'), t('warning'),
{
confirmButtonText: t('confirm'),
cancelButtonText: t('cancel'),
type: 'warning',
}
).then(() => {
deleteSales(id).then(() => {
loadSalesList()
}).catch(() => {
})
})
}
const addStaffIdList = ref([])
const setAddStaffIdList = async () => {
addStaffIdList.value = await (await getWithStaffList({})).data
}
setAddStaffIdList()
const getStaffIdList = ref([])
const setGetStaffIdList = async () => {
getStaffIdList.value = await (await getWithStaffList({})).data
}
setGetStaffIdList()
const provinceIdList = ref([])
const setProvinceIdList = async () => {
provinceIdList.value = await (await getWithSysAreaList({})).data
}
setProvinceIdList()
const cityIdList = ref([])
const setCityIdList = async () => {
cityIdList.value = await (await getWithSysAreaList({})).data
}
setCityIdList()
const districtIdList = ref([])
const setDistrictIdList = async () => {
districtIdList.value = await (await getWithSysAreaList({})).data
}
setDistrictIdList()
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return
formEl.resetFields()
loadSalesList()
}
</script>
<style lang="scss" scoped>
/* 多行超出隐藏 */
.multi-hidden {
word-break: break-all;
text-overflow: ellipsis;
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
</style>

418
niucloud/addon/zhjw/admin/views/sales/sales_edit.vue

@ -0,0 +1,418 @@
<template>
<div class="main-container">
<div class="detail-head">
<div class="left" @click="back()">
<span class="iconfont iconxiangzuojiantou !text-xs"></span>
<span class="ml-[1px]">{{t('returnToPreviousPage')}}</span>
</div>
<span class="adorn">|</span>
<span class="right">{{ pageName }}</span>
</div>
<el-card class="box-card !border-none" shadow="never">
<el-form :model="formData" label-width="90px" ref="formRef" :rules="formRules" class="page-form">
<el-form-item :label="t('studentPhone')" prop="student_phone">
<el-input v-model="formData.student_phone" clearable :placeholder="t('studentPhonePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('studentName')" prop="student_name">
<el-input v-model="formData.student_name" clearable :placeholder="t('studentNamePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('sex')" prop="sex">
<el-select class="input-width" v-model="formData.sex" clearable :placeholder="t('sexPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in sexList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('age')" prop="age">
<el-input-number v-model="formData.age" clearable :placeholder="t('agePlaceholder')" class="input-width" :min = "0" max = "300" />
</el-form-item>
<el-form-item :label="t('schoolName')" prop="school_name">
<el-input v-model="formData.school_name" clearable :placeholder="t('schoolNamePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('grade')" >
<el-input v-model="formData.grade" clearable :placeholder="t('gradePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('className')" >
<el-input v-model="formData.class_name" clearable :placeholder="t('classNamePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('sourceChannel')" prop="source_channel">
<el-select class="input-width" v-model="formData.source_channel" clearable :placeholder="t('sourceChannelPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in source_channelList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('customerSource')" prop="customer_source">
<el-select class="input-width" v-model="formData.customer_source" clearable :placeholder="t('customerSourcePlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in customer_sourceList"
:key="index"
:label="item.name"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('addStaffId')" prop="add_staff_id">
<el-select class="input-width" v-model="formData.add_staff_id" clearable :placeholder="t('addStaffIdPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in addStaffIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('getStaffId')" >
<el-select class="input-width" v-model="formData.get_staff_id" clearable :placeholder="t('getStaffIdPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in getStaffIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('contactName')" prop="contact_name">
<el-input v-model="formData.contact_name" clearable :placeholder="t('contactNamePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('provinceId')" >
<el-select class="input-width" v-model="formData.province_id" clearable :placeholder="t('provinceIdPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in provinceIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('cityId')" >
<el-select class="input-width" v-model="formData.city_id" clearable :placeholder="t('cityIdPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in cityIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('districtId')" >
<el-select class="input-width" v-model="formData.district_id" clearable :placeholder="t('districtIdPlaceholder')">
<el-option label="请选择" value=""></el-option>
<el-option
v-for="(item, index) in districtIdList"
:key="index"
:label="item['name']"
:value="item['id']"
/>
</el-select>
</el-form-item>
<el-form-item :label="t('communityName')" >
<el-input v-model="formData.community_name" clearable :placeholder="t('communityNamePlaceholder')" class="input-width" />
</el-form-item>
<el-form-item :label="t('customerTags')" >
<el-checkbox-group v-model="formData.customer_tags" :placeholder="t('customerTagsPlaceholder')">
<el-checkbox
v-for="(item, index) in customer_tagsList"
:key="index"
:label="item.value">
{{ item.name }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-form>
</el-card>
<div class="fixed-footer-wrap">
<div class="fixed-footer">
<el-button type="primary" @click="onSave(formRef)">{{ t('save') }}</el-button>
<el-button @click="back()">{{ t('cancel') }}</el-button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, computed, watch } from 'vue'
import { t } from '@/lang'
import { useDictionary } from '@/app/api/dict'
import type { FormInstance } from 'element-plus'
import { getSalesInfo,addSales,editSales, getWithStaffList, getWithStaffList, getWithSysAreaList, getWithSysAreaList, getWithSysAreaList } from '@/addon/zhjw/api/sales';
import { useRoute } from 'vue-router'
const route = useRoute()
const id:number = parseInt(route.query.id);
const loading = ref(false)
const pageName = route.meta.title
/**
* 表单数据
*/
const initialFormData = {
id: 0,
student_phone: '',
student_name: '',
sex: '',
age: '',
school_name: '',
grade: '',
class_name: '',
source_channel: '',
customer_source: '',
add_staff_id: '',
get_staff_id: '',
contact_name: '',
province_id: '',
city_id: '',
district_id: '',
community_name: '',
customer_tags: '',
}
const formData: Record<string, any> = reactive({ ...initialFormData })
const setFormData = async (id:number = 0) => {
Object.assign(formData, initialFormData)
const data = await (await getSalesInfo(id)).data
Object.keys(formData).forEach((key: string) => {
if (data[key] != undefined) formData[key] = data[key]
})
}
if(id) setFormData(id);
const formRef = ref<FormInstance>()
//
const selectData = ref<any[]>([])
//
let sexList = ref([])
const sexDictList = async () => {
sexList.value = await (await useDictionary('users_sex')).data.dictionary
}
sexDictList();
watch(() => sexList.value, () => { formData.sex = sexList.value[0].value })
let source_channelList = ref([])
const source_channelDictList = async () => {
source_channelList.value = await (await useDictionary('source_channel')).data.dictionary
}
source_channelDictList();
watch(() => source_channelList.value, () => { formData.source_channel = source_channelList.value[0].value })
let customer_sourceList = ref([])
const customer_sourceDictList = async () => {
customer_sourceList.value = await (await useDictionary('customer_source')).data.dictionary
}
customer_sourceDictList();
watch(() => customer_sourceList.value, () => { formData.customer_source = customer_sourceList.value[0].value })
let customer_tagsList = ref([])
const customer_tagsDictList = async () => {
customer_tagsList.value = await (await useDictionary('customer_tags')).data.dictionary
}
customer_tagsDictList();
const addStaffIdList = ref([] as any[])
const setAddStaffIdList = async () => {
addStaffIdList.value = await (await getWithStaffList({})).data
}
setAddStaffIdList()
const getStaffIdList = ref([] as any[])
const setGetStaffIdList = async () => {
getStaffIdList.value = await (await getWithStaffList({})).data
}
setGetStaffIdList()
const provinceIdList = ref([] as any[])
const setProvinceIdList = async () => {
provinceIdList.value = await (await getWithSysAreaList({})).data
}
setProvinceIdList()
const cityIdList = ref([] as any[])
const setCityIdList = async () => {
cityIdList.value = await (await getWithSysAreaList({})).data
}
setCityIdList()
const districtIdList = ref([] as any[])
const setDistrictIdList = async () => {
districtIdList.value = await (await getWithSysAreaList({})).data
}
setDistrictIdList()
//
const formRules = computed(() => {
return {
student_phone: [
{ required: true, message: t('studentPhonePlaceholder'), trigger: 'blur' },
]
,
student_name: [
{ required: true, message: t('studentNamePlaceholder'), trigger: 'blur' },
]
,
sex: [
{ required: true, message: t('sexPlaceholder'), trigger: 'blur' },
]
,
age: [
{ required: true, message: t('agePlaceholder'), trigger: 'blur' },
{ validator: (rule: any, value: string, callback: any) => { if (value && !/^\d{0,300}$/.test(value)) { callback(new Error(t('generateBetween')))} else { callback() }}},
]
,
school_name: [
{ required: true, message: t('schoolNamePlaceholder'), trigger: 'blur' },
]
,
grade: [
{ required: true, message: t('gradePlaceholder'), trigger: 'blur' },
]
,
class_name: [
{ required: true, message: t('classNamePlaceholder'), trigger: 'blur' },
]
,
source_channel: [
{ required: true, message: t('sourceChannelPlaceholder'), trigger: 'blur' },
]
,
customer_source: [
{ required: true, message: t('customerSourcePlaceholder'), trigger: 'blur' },
]
,
add_staff_id: [
{ required: true, message: t('addStaffIdPlaceholder'), trigger: 'blur' },
]
,
get_staff_id: [
{ required: true, message: t('getStaffIdPlaceholder'), trigger: 'blur' },
]
,
contact_name: [
{ required: true, message: t('contactNamePlaceholder'), trigger: 'blur' },
]
,
province_id: [
{ required: true, message: t('provinceIdPlaceholder'), trigger: 'blur' },
]
,
city_id: [
{ required: true, message: t('cityIdPlaceholder'), trigger: 'blur' },
]
,
district_id: [
{ required: true, message: t('districtIdPlaceholder'), trigger: 'blur' },
]
,
community_name: [
{ required: true, message: t('communityNamePlaceholder'), trigger: 'blur' },
]
,
customer_tags: [
{ required: true, message: t('customerTagsPlaceholder'), trigger: 'blur' },
]
,
}
})
const onSave = async (formEl: FormInstance | undefined) => {
if (loading.value || !formEl) return
await formEl.validate(async (valid) => {
if (valid) {
loading.value = true
let data = formData
const save = id ? editSales : addSales
save(data).then(res => {
loading.value = false
history.back()
}).catch(err => {
loading.value = false
})
}
})
}
//
const mobileVerify = (rule: any, value: any, callback: any) => {
if (value && !/^1[3-9]\d{9}$/.test(value)) {
callback(new Error(t('generateMobile')))
} else {
callback()
}
}
//
const idCardVerify = (rule: any, value: any, callback: any) => {
if (value && !/^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value)) {
callback(new Error(t('generateIdCard')))
} else {
callback()
}
}
//
const emailVerify = (rule: any, value: any, callback: any) => {
if (value && !/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(value)) {
callback(new Error(t('generateEmail')))
} else {
callback()
}
}
//
const numberVerify = (rule: any, value: any, callback: any) => {
if (!Number.isInteger(value)) {
callback(new Error(t('generateNumber')))
} else {
callback()
}
}
const back = () => {
history.back()
}
</script>
<style lang="scss" scoped></style>

142
niucloud/addon/zhjw/app/adminapi/controller/sales/Sales.php

@ -0,0 +1,142 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\zhjw\app\adminapi\controller\sales;
use core\base\BaseAdminController;
use addon\zhjw\app\service\admin\sales\SalesService;
/**
* 销售管理控制器
* Class Sales
* @package addon\zhjw\app\adminapi\controller\sales
*/
class Sales extends BaseAdminController
{
/**
* 获取销售管理列表
* @return \think\Response
*/
public function lists(){
$data = $this->request->params([
["student_phone",""],
["student_name",""],
["sex",""],
["age",["",""]],
["school_name",""],
["grade",""],
["class_name",""],
["source_channel",""],
["customer_source",""],
["add_staff_id",""],
["get_staff_id",""],
["contact_name",""],
["province_id",""],
["city_id",""],
["district_id",""],
["community_name",""],
["customer_tags",""],
["create_time",""]
]);
return success((new SalesService())->getPage($data));
}
/**
* 销售管理详情
* @param int $id
* @return \think\Response
*/
public function info(int $id){
return success((new SalesService())->getInfo($id));
}
/**
* 添加销售管理
* @return \think\Response
*/
public function add(){
$data = $this->request->params([
["student_phone",""],
["student_name",""],
["sex",""],
["age",""],
["school_name",""],
["grade",""],
["class_name",""],
["source_channel",""],
["customer_source",""],
["add_staff_id",0],
["get_staff_id",0],
["contact_name",""],
["province_id",0],
["city_id",0],
["district_id",0],
["community_name",""],
["customer_tags",""],
]);
$this->validate($data, 'addon\zhjw\app\validate\sales\Sales.add');
$id = (new SalesService())->add($data);
return success('ADD_SUCCESS', ['id' => $id]);
}
/**
* 销售管理编辑
* @param $id 销售管理id
* @return \think\Response
*/
public function edit(int $id){
$data = $this->request->params([
["student_phone",""],
["student_name",""],
["sex",""],
["age",""],
["school_name",""],
["grade",""],
["class_name",""],
["source_channel",""],
["customer_source",""],
["add_staff_id",0],
["get_staff_id",0],
["contact_name",""],
["province_id",0],
["city_id",0],
["district_id",0],
["community_name",""],
["customer_tags",""],
]);
$this->validate($data, 'addon\zhjw\app\validate\sales\Sales.edit');
(new SalesService())->edit($id, $data);
return success('EDIT_SUCCESS');
}
/**
* 销售管理删除
* @param $id 销售管理id
* @return \think\Response
*/
public function del(int $id){
(new SalesService())->del($id);
return success('DELETE_SUCCESS');
}
public function getStaffAll(){
return success(( new SalesService())->getStaffAll());
}
public function getSysAreaAll(){
return success(( new SalesService())->getSysAreaAll());
}
}

26
niucloud/addon/zhjw/app/adminapi/route/route.php

@ -355,3 +355,29 @@ Route::group('zhjw', function () {
AdminLog::class
]);
// USER_CODE_END -- timetables
// USER_CODE_BEGIN -- zhjw_sales
Route::group('zhjw', function () {
//销售管理列表
Route::get('sales', 'addon\zhjw\app\adminapi\controller\sales\Sales@lists');
//销售管理详情
Route::get('sales/:id', 'addon\zhjw\app\adminapi\controller\sales\Sales@info');
//添加销售管理
Route::post('sales', 'addon\zhjw\app\adminapi\controller\sales\Sales@add');
//编辑销售管理
Route::put('sales/:id', 'addon\zhjw\app\adminapi\controller\sales\Sales@edit');
//删除销售管理
Route::delete('sales/:id', 'addon\zhjw\app\adminapi\controller\sales\Sales@del');
Route::get('staff_all','addon\zhjw\app\adminapi\controller\sales\Sales@getStaffAll');
Route::get('sys_area_all','addon\zhjw\app\adminapi\controller\sales\Sales@getSysAreaAll');
})->middleware([
AdminCheckToken::class,
AdminCheckRole::class,
AdminLog::class
]);
// USER_CODE_END -- zhjw_sales

295
niucloud/addon/zhjw/app/model/sales/Sales.php

@ -0,0 +1,295 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\zhjw\app\model\sales;
use core\base\BaseModel;
use think\model\concern\SoftDelete;
use think\model\relation\HasMany;
use think\model\relation\HasOne;
use addon\zhjw\app\model\staff\Staff;
use app\model\sys\SysArea;
/**
* 销售管理模型
* Class Sales
* @package addon\zhjw\app\model\sales
*/
class Sales extends BaseModel
{
use SoftDelete;
/**
* 数据表主键
* @var string
*/
protected $pk = 'id';
/**
* 模型名称
* @var string
*/
protected $name = 'zhjw_sales';
/**
* 定义软删除标记字段.
* @var string
*/
protected $deleteTime = 'is_deleted';
/**
* 定义软删除字段的默认值.
* @var int
*/
protected $defaultSoftDelete = 0;
/**
* 搜索器:销售管理学生手机号
* @param $value
* @param $data
*/
public function searchStudentPhoneAttr($query, $value, $data)
{
if ($value) {
$query->where("student_phone", "like", "%".$value."%");
}
}
/**
* 搜索器:销售管理学生姓名
* @param $value
* @param $data
*/
public function searchStudentNameAttr($query, $value, $data)
{
if ($value) {
$query->where("student_name", "like", "%".$value."%");
}
}
/**
* 搜索器:销售管理性别
* @param $value
* @param $data
*/
public function searchSexAttr($query, $value, $data)
{
if ($value) {
$query->where("sex", $value);
}
}
/**
* 搜索器:销售管理年龄
* @param $value
* @param $data
*/
public function searchAgeAttr($query, $value, $data)
{
$start = empty($value[0]) ? 0 : $value[0];
$end = empty($value[1]) ? 0 : $value[1];
if ($start > 0 && $end > 0) {
$query->where([["age", "between", [$start, $end]]]);
} else if ($start > 0 && $end == 0) {
$query->where([["age", ">=", $start]]);
} else if ($start == 0 && $end > 0) {
$query->where([["age", "<=", $end]]);
}
}
/**
* 搜索器:销售管理学校名称
* @param $value
* @param $data
*/
public function searchSchoolNameAttr($query, $value, $data)
{
if ($value) {
$query->where("school_name", "like", "%".$value."%");
}
}
/**
* 搜索器:销售管理年级
* @param $value
* @param $data
*/
public function searchGradeAttr($query, $value, $data)
{
if ($value) {
$query->where("grade", "like", "%".$value."%");
}
}
/**
* 搜索器:销售管理班级名称
* @param $value
* @param $data
*/
public function searchClassNameAttr($query, $value, $data)
{
if ($value) {
$query->where("class_name", "like", "%".$value."%");
}
}
/**
* 搜索器:销售管理来源渠道
* @param $value
* @param $data
*/
public function searchSourceChannelAttr($query, $value, $data)
{
if ($value) {
$query->where("source_channel", $value);
}
}
/**
* 搜索器:销售管理客户来源
* @param $value
* @param $data
*/
public function searchCustomerSourceAttr($query, $value, $data)
{
if ($value) {
$query->where("customer_source", $value);
}
}
/**
* 搜索器:销售管理添加这条数据的工作人员
* @param $value
* @param $data
*/
public function searchAddStaffIdAttr($query, $value, $data)
{
if ($value) {
$query->where("add_staff_id", $value);
}
}
/**
* 搜索器:销售管理领取这条客户数据的工作人员
* @param $value
* @param $data
*/
public function searchGetStaffIdAttr($query, $value, $data)
{
if ($value) {
$query->where("get_staff_id", $value);
}
}
/**
* 搜索器:销售管理联系人姓名
* @param $value
* @param $data
*/
public function searchContactNameAttr($query, $value, $data)
{
if ($value) {
$query->where("contact_name", "like", "%".$value."%");
}
}
/**
* 搜索器:销售管理所在地-省
* @param $value
* @param $data
*/
public function searchProvinceIdAttr($query, $value, $data)
{
if ($value) {
$query->where("province_id", $value);
}
}
/**
* 搜索器:销售管理所在地-市
* @param $value
* @param $data
*/
public function searchCityIdAttr($query, $value, $data)
{
if ($value) {
$query->where("city_id", $value);
}
}
/**
* 搜索器:销售管理所在地-区
* @param $value
* @param $data
*/
public function searchDistrictIdAttr($query, $value, $data)
{
if ($value) {
$query->where("district_id", $value);
}
}
/**
* 搜索器:销售管理小区名称
* @param $value
* @param $data
*/
public function searchCommunityNameAttr($query, $value, $data)
{
if ($value) {
$query->where("community_name", $value);
}
}
/**
* 搜索器:销售管理客户标签
* @param $value
* @param $data
*/
public function searchCustomerTagsAttr($query, $value, $data)
{
if ($value) {
$query->where("customer_tags", $value);
}
}
/**
* 搜索器:销售管理添加时间
* @param $value
* @param $data
*/
public function searchCreateTimeAttr($query, $value, $data)
{
if ($value) {
$query->where("create_time", $value);
}
}
public function staff(){
return $this->hasOne(Staff::class, 'id', 'add_staff_id')->joinType('left')->withField('name,id')->bind(['add_staff_id_name'=>'name']);
}
public function sysArea(){
return $this->hasOne(SysArea::class, 'id', 'province_id')->joinType('left')->withField('name,id')->bind(['province_id_name'=>'name']);
}
}

112
niucloud/addon/zhjw/app/service/admin/sales/SalesService.php

@ -0,0 +1,112 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\zhjw\app\service\admin\sales;
use addon\zhjw\app\model\sales\Sales;
use addon\zhjw\app\model\staff\Staff;
use app\model\sys\SysArea;
use core\base\BaseAdminService;
/**
* 销售管理服务层
* Class SalesService
* @package addon\zhjw\app\service\admin\sales
*/
class SalesService extends BaseAdminService
{
public function __construct()
{
parent::__construct();
$this->model = new Sales();
}
/**
* 获取销售管理列表
* @param array $where
* @return array
*/
public function getPage(array $where = [])
{
$field = 'id,student_phone,student_name,sex,age,school_name,grade,class_name,source_channel,customer_source,add_staff_id,get_staff_id,contact_name,province_id,city_id,district_id,full_address,community_name,customer_tags,create_time,update_time,is_deleted,created_by,created_role,updated_by,updated_role';
$order = 'id desc';
$search_model = $this->model->withSearch(["student_phone","student_name","sex","age","school_name","grade","class_name","source_channel","customer_source","add_staff_id","get_staff_id","contact_name","province_id","city_id","district_id","community_name","customer_tags","create_time"], $where)->with(['staff','staff','sysArea','sysArea','sysArea'])->field($field)->order($order);
$list = $this->pageQuery($search_model);
return $list;
}
/**
* 获取销售管理信息
* @param int $id
* @return array
*/
public function getInfo(int $id)
{
$field = 'id,student_phone,student_name,sex,age,school_name,grade,class_name,source_channel,customer_source,add_staff_id,get_staff_id,contact_name,province_id,city_id,district_id,full_address,community_name,customer_tags,create_time,update_time,is_deleted,created_by,created_role,updated_by,updated_role';
$info = $this->model->field($field)->where([['id', "=", $id]])->with(['staff','staff','sysArea','sysArea','sysArea'])->findOrEmpty()->toArray();
return $info;
}
/**
* 添加销售管理
* @param array $data
* @return mixed
*/
public function add(array $data)
{
$res = $this->model->create($data);
return $res->id;
}
/**
* 销售管理编辑
* @param int $id
* @param array $data
* @return bool
*/
public function edit(int $id, array $data)
{
$this->model->where([['id', '=', $id]])->update($data);
return true;
}
/**
* 删除销售管理
* @param int $id
* @return bool
*/
public function del(int $id)
{
$model = $this->model->where([['id', '=', $id]])->find();
$res = $model->delete();
return $res;
}
public function getStaffAll(){
$staffModel = new Staff();
return $staffModel->select()->toArray();
}
public function getSysAreaAll(){
$sysAreaModel = new SysArea();
return $sysAreaModel->select()->toArray();
}
}

52
niucloud/addon/zhjw/app/validate/sales/Sales.php

@ -0,0 +1,52 @@
<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址:https://www.niucloud.com
// +----------------------------------------------------------------------
// | niucloud团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: Niucloud Team
// +----------------------------------------------------------------------
namespace addon\zhjw\app\validate\sales;
use core\base\BaseValidate;
/**
* 销售管理验证器
* Class Sales
* @package addon\zhjw\app\validate\sales
*/
class Sales extends BaseValidate
{
protected $rule = [
'student_phone' => 'require',
'student_name' => 'require',
'sex' => 'require',
'age' => 'require|between:0,300',
'school_name' => 'require',
'source_channel' => 'require',
'customer_source' => 'require',
'add_staff_id' => 'require',
'contact_name' => 'require',
];
protected $message = [
'student_phone.require' => ['common_validate.require', ['student_phone']],
'student_name.require' => ['common_validate.require', ['student_name']],
'sex.require' => ['common_validate.require', ['sex']],
'age.require' => ['common_validate.require', ['age']],
'age.between' => ['common_validate.between', ['age','0','300']],
'school_name.require' => ['common_validate.require', ['school_name']],
'source_channel.require' => ['common_validate.require', ['source_channel']],
'customer_source.require' => ['common_validate.require', ['customer_source']],
'add_staff_id.require' => ['common_validate.require', ['add_staff_id']],
'contact_name.require' => ['common_validate.require', ['contact_name']],
];
protected $scene = [
"add" => ['student_phone', 'student_name', 'sex', 'age', 'school_name', 'grade', 'class_name', 'source_channel', 'customer_source', 'add_staff_id', 'get_staff_id', 'contact_name', 'province_id', 'city_id', 'district_id', 'community_name', 'customer_tags'],
"edit" => ['student_phone', 'student_name', 'sex', 'age', 'school_name', 'grade', 'class_name', 'source_channel', 'customer_source', 'add_staff_id', 'get_staff_id', 'contact_name', 'province_id', 'city_id', 'district_id', 'community_name', 'customer_tags']
];
}
Loading…
Cancel
Save