From 5b3e02b447fb3b7f19ed26abd040d2e84b52ab6a Mon Sep 17 00:00:00 2001 From: qsh <> Date: Fri, 7 Jun 2024 17:01:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/clue/clueField.js | 40 ++++ src/api/clue/clueGetSet.js | 21 ++ src/api/clue/orderField.js | 40 ++++ src/api/clue/source.js | 31 +++ src/config/axios/service.ts | 2 +- src/views/Clue/Set/Comp/ClueGet.vue | 86 +++---- src/views/Clue/Set/Comp/ClueSend.vue | 65 ++++-- src/views/Clue/Set/Comp/ClueSource.vue | 77 ++++--- src/views/Clue/Set/Comp/DialogSource.vue | 37 +-- src/views/Clue/Set/Comp/FieldClue.vue | 216 +++++++++++++----- src/views/Clue/Set/Comp/FieldOrder.vue | 216 +++++++++++++----- src/views/Clue/Set/index.vue | 45 ++-- src/views/Clue/Skill/index.vue | 28 ++- .../Inventory/Comp/InventoryRecord.vue | 8 +- .../MiniMall/Inventory/Comp/Warehouse.vue | 9 +- 15 files changed, 682 insertions(+), 239 deletions(-) create mode 100644 src/api/clue/clueField.js create mode 100644 src/api/clue/clueGetSet.js create mode 100644 src/api/clue/orderField.js create mode 100644 src/api/clue/source.js diff --git a/src/api/clue/clueField.js b/src/api/clue/clueField.js new file mode 100644 index 0000000..2d386a2 --- /dev/null +++ b/src/api/clue/clueField.js @@ -0,0 +1,40 @@ +import request from '@/config/axios' + +// 创建 +export const createField = (data) => { + return request.post({ url: '/admin-api/crm/clue-param/create', data }) +} + +// 更新 +export const updateField = (data) => { + return request.put({ url: '/admin-api/crm/clue-param/update', data }) +} + +// 删除 +export const deleteField = (id) => { + return request.delete({ url: `/admin-api/crm/clue-param/delete?id=${id}` }) +} + +// 获得 +export const getField = (id) => { + return request.get({ url: `/admin-api/crm/clue-param/get?id=${id}` }) +} + +// 获得精简信息列表 +export const getSimpleFieldList = () => { + return request.get({ url: '/admin-api/crm/clue-param/simple-list' }) +} + +// 获取自定义字段 +export const getDiyFieldList = () => { + return request.get({ url: '/admin-api/crm/clue-param/get-diy-param' }) +} + +// 状态修改 +export const updateFieldStatus = (signParamId, status) => { + const data = { + signParamId, + status + } + return request.put({ url: '/admin-api/crm/clue-param/status/update', data: data }) +} diff --git a/src/api/clue/clueGetSet.js b/src/api/clue/clueGetSet.js new file mode 100644 index 0000000..989dbe2 --- /dev/null +++ b/src/api/clue/clueGetSet.js @@ -0,0 +1,21 @@ +import request from '@/config/axios' + +// 线索获取规则 +export const getClueGainRuleList = () => { + return request.get({ url: '/admin-api/crm/sch-clue-gain-rule/list' }) +} + +// 删除 +export const deleteClueGainRule = (id) => { + return request.delete({ url: `/admin-api/crm/sch-clue-gain-rule/delete?id=${id}` }) +} + +// 线索规则 +export const getClueDistributeRuleList = () => { + return request.get({ url: '/admin-api/crm/sch-clue-gain-rule/list' }) +} + +// 删除 +export const deleteClueDistributeRule = (id) => { + return request.delete({ url: `/admin-api/crm/sch-clue-gain-rule/delete?id=${id}` }) +} diff --git a/src/api/clue/orderField.js b/src/api/clue/orderField.js new file mode 100644 index 0000000..23dd285 --- /dev/null +++ b/src/api/clue/orderField.js @@ -0,0 +1,40 @@ +import request from '@/config/axios' + +// 创建 +export const createField = (data) => { + return request.post({ url: '/admin-api/crm/sign-param/create', data }) +} + +// 更新 +export const updateField = (data) => { + return request.put({ url: '/admin-api/crm/sign-param/update', data }) +} + +// 删除 +export const deleteField = (id) => { + return request.delete({ url: `/admin-api/crm/sign-param/delete?id=${id}` }) +} + +// 获得 +export const getField = (id) => { + return request.get({ url: `/admin-api/crm/sign-param/get?id=${id}` }) +} + +// 获得精简信息列表 +export const getSimpleFieldList = () => { + return request.get({ url: '/admin-api/crm/sign-param/simple-list' }) +} + +// 获取自定义字段 +export const getDiyFieldList = () => { + return request.get({ url: '/admin-api/crm/sign-param/get-diy-param' }) +} + +// 状态修改 +export const updateFieldStatus = (signParamId, status) => { + const data = { + signParamId, + status + } + return request.put({ url: '/admin-api/crm/sign-param/status/update', data: data }) +} diff --git a/src/api/clue/source.js b/src/api/clue/source.js new file mode 100644 index 0000000..d0d3890 --- /dev/null +++ b/src/api/clue/source.js @@ -0,0 +1,31 @@ +import request from '@/config/axios' + +// 查询(精简)列表 +export const getSimpleSourceList = async () => { + return await request.get({ url: '/admin-api/crm/source/list-all-simple' }) +} + +// 查询列表 +export const getSourcePage = async (params) => { + return await request.get({ url: '/admin-api/crm/source/list', params }) +} + +// 查询详情 +export const getSource = async (id) => { + return await request.get({ url: '/admin-api/crm/source/get?id=' + id }) +} + +// 新增 +export const createSource = async (data) => { + return await request.post({ url: '/admin-api/crm/source/create', data: data }) +} + +// 修改 +export const updateSource = async (params) => { + return await request.put({ url: '/admin-api/crm/source/update', data: params }) +} + +// 删除 +export const deleteSource = async (id) => { + return await request.delete({ url: '/admin-api/crm/source/delete?id=' + id }) +} diff --git a/src/config/axios/service.ts b/src/config/axios/service.ts index 9453910..bca3e1f 100644 --- a/src/config/axios/service.ts +++ b/src/config/axios/service.ts @@ -179,7 +179,7 @@ service.interceptors.response.use( }) } } else if (code === 500) { - ElMessage.error(t('sys.api.errMsg500')) + ElMessage.error(t(msg || 'sys.api.errMsg500')) return Promise.reject(new Error(msg)) } else if (code === 901) { ElMessage.error({ diff --git a/src/views/Clue/Set/Comp/ClueGet.vue b/src/views/Clue/Set/Comp/ClueGet.vue index 038a7e2..9e33da0 100644 --- a/src/views/Clue/Set/Comp/ClueGet.vue +++ b/src/views/Clue/Set/Comp/ClueGet.vue @@ -1,10 +1,10 @@ <template> <div> - <el-table :data="list" border> + <el-table v-loading="loading" :data="list" border> <el-table-column type="index" width="50" /> <el-table-column label="来源名称" width="200px"> <template #default="{ row }"> - <el-input v-model="row.name" placeholder="请输入" :clearable="false" /> + <el-input v-model="row.source" placeholder="请输入" :clearable="false" /> </template> </el-table-column> <el-table-column label="渠道" width="300px"> @@ -24,14 +24,14 @@ :value="item.value" /> </el-select> - <span>{{ row.resourceName }}</span> + <span>{{ row.channel }}</span> </template> </el-table-column> - <el-table-column label="获取连接" prop="link" /> + <el-table-column label="获取连接" prop="url" /> <el-table-column label="参数详情" prop="params" /> <el-table-column label="是否启用" width="100px"> <template #default="{ row }"> - <el-switch v-model="row.inEnable" :active-value="true" :inactive-value="false" /> + <el-switch v-model="row.status" :active-value="0" :inactive-value="1" /> </template> </el-table-column> <el-table-column label="操作" width="100px"> @@ -49,56 +49,60 @@ </div> </template> -<script setup> -const list = ref([ - { - name: '一点通账号1', - resourceName: '驾校一点通', - link: 'https://sscrm.ahduima.com/clue/get?cid=1001&aid=1001&res=2', - params: '参数详情' - }, - { - name: '一点通账号2', - resourceName: '驾校一点通', - link: 'https://sscrm.ahduima.com/clue/get?cid=1001&aid=1001&res=2', - params: '参数详情' - }, - { - name: '宝典账号', - resourceName: '驾考宝典', - link: 'https://sscrm.ahduima.com/clue/get?cid=1001&aid=1001&res=1', - params: '参数详情' - }, - { - name: '抖音', - resourceName: '抖音/开心学车', - link: 'https://sscrm.ahduima.com/clue/get?cid=1001&aid=1001&res=3', - params: '参数详情' - } -]) +<script setup name="ClueSet"> +import { getClueGainRuleList, deleteClueGainRule } from '@/api/clue/clueGetSet' + +const message = useMessage() // 消息弹窗 +const { t } = useI18n() // 国际化 -const resourceOptions = ref([ - { value: 1, label: '驾考宝典' }, - { value: 2, label: '一点通' }, - { value: 3, label: '抖音' } -]) +const list = ref([]) +const loading = ref(false) +const resourceOptions = ref([]) + +async function getList() { + loading.value = true + try { + const data = await getClueGainRuleList() + list.value = data + } finally { + loading.value = false + } +} function handleInsert() { - list.value.push({ name: '', link: '', edit: true, inEnable: true }) + list.value.push({ source: '', url: '', edit: true, status: 0 }) } function onSubmit() { console.log('保存成功') } -function handleRemove(idx) { - list.value.splice(idx, 1) +async function handleRemove(idx) { + if (list.value[idx].ruleId) { + try { + // 删除的二次确认 + await message.delConfirm() + // 发起删除 + await deleteClueGainRule(list.value[idx].ruleId) + message.success(t('common.delSuccess')) + // 刷新列表 + await getList() + } catch (err) { + console.log(err) + } + } else { + list.value.splice(idx, 1) + } } function handleChange(row) { - row.link = `https://sscrm.ahduima.com/clue/get?cid=1001&aid=1001&res=${row.resource}` + row.url = `https://sscrm.ahduima.com/clue/get?cid=1001&aid=1001&res=${row.resource}` row.params = '参数详情' } + +onMounted(() => { + getList() +}) </script> <style lang="scss" scoped></style> diff --git a/src/views/Clue/Set/Comp/ClueSend.vue b/src/views/Clue/Set/Comp/ClueSend.vue index 161f7ce..358973c 100644 --- a/src/views/Clue/Set/Comp/ClueSend.vue +++ b/src/views/Clue/Set/Comp/ClueSend.vue @@ -2,22 +2,33 @@ <div class="flex"> <div class="mr-20px" style="width: 500px"> <el-input - v-model="searchForm.keyword" + v-model="searchForm.nickname" placeholder="请输入关键字查询" clearable class="mb-10px" @keyup.enter="getUserList" /> - <el-table :data="userList" @cell-click="selectUser"> - <el-table-column prop="name" label="员工姓名" /> - <el-table-column prop="phone" label="电话" /> - <el-table-column prop="workNum" label="工号" /> + <el-table + v-loading="loading" + :data="userList" + :row-class-name="setRowClass" + @row-click="handleRowClick" + > + <el-table-column prop="nickname" label="员工姓名" /> + <el-table-column prop="mobile" label="电话" /> + <el-table-column prop="status" label="状态"> + <template #default="{ row }"> + {{ ['在职', '离职'][row.status] }} + </template> + </el-table-column> </el-table> <!-- 分页 --> <Pagination v-model:limit="searchForm.pageSize" - v-model:page="searchForm.pageNum" + v-model:page="searchForm.pageNo" + small + layout="total, prev, pager, next, jumper" :total="total" @pagination="getUserList" /> @@ -65,16 +76,27 @@ </div> </template> -<script setup> +<script setup name="ClueSend"> +import { getUserPage } from '@/api/system/user' + +// const message = useMessage() // 消息弹窗 +// const { t } = useI18n() // 国际化 + const searchForm = ref({ - keyword: '', + nickname: '', pageSize: 20, - pageNum: 1 + pageNo: 1 }) const total = ref(0) +const loading = ref(false) +const userList = ref([]) + +function setRowClass({ row }) { + return row.field == currentRowId.value ? 'current-row' : '' +} -const userList = ref([{ name: '张三', phone: '1888888888', workNum: '202101030001' }]) +const currentRowId = ref('') const form = ref({ isAuto: 1, @@ -84,8 +106,18 @@ const form = ref({ }) const rules = ref({}) -function getUserList() { - console.log('获取列表') +async function getUserList() { + loading.value = true + try { + const data = await getUserPage(searchForm.value) + userList.value = data.list + if (userList.value.length) { + handleRowClick(userList.value[0]) + } + total.value = data.total + } finally { + loading.value = false + } } function onSubmit() { @@ -111,9 +143,14 @@ function resourceCheckedChange(val) { resourceIndeterminate.value = checkedCount > 0 && checkedCount < resourceOptions.value.length } -function selectUser(row) { - console.log(row) +function handleRowClick(row) { + currentRowId.value = row.ruleId + form.value = { ...row } } + +onMounted(() => { + getUserList() +}) </script> <style lang="scss" scoped></style> diff --git a/src/views/Clue/Set/Comp/ClueSource.vue b/src/views/Clue/Set/Comp/ClueSource.vue index 3968c0f..e27a7a2 100644 --- a/src/views/Clue/Set/Comp/ClueSource.vue +++ b/src/views/Clue/Set/Comp/ClueSource.vue @@ -1,9 +1,9 @@ <template> <div> - <el-form ref="queryForm" :model="searchForm" label-width="0" inline> + <el-form ref="queryForm" :model="searchForm" label-width="0" inline @submit.prevent> <el-form-item> <el-input - v-model="searchForm.name" + v-model="searchForm.sourceName" placeholder="请输入名称" clearable @keyup.enter="handleQuery" @@ -22,84 +22,89 @@ :tree-props="{ children: 'children' }" > <el-table-column prop="sourceName" label="来源名称" /> - <el-table-column prop="orderNum" label="排序" width="100px" /> + <el-table-column prop="sort" label="排序" width="100px" /> <el-table-column prop="remark" label="备注" /> - <el-table-column label="创建时间" prop="createTime" width="180px" /> - <el-table-column label="创建人" prop="createUser" width="150px" /> + <el-table-column + label="创建时间" + prop="createTime" + width="180px" + :formatter="dateFormatter" + /> + <el-table-column label="状态"> + <template #default="{ row }"> + <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" /> + </template> + </el-table-column> <el-table-column label="操作"> - <template #default="scope"> - <el-button type="primary" text @click="openForm('update', scope.row)">修改</el-button> - <el-button type="primary" text @click="openForm('createChildren', scope.row)" - >新增</el-button - > - <el-button type="danger" text @click="handleDelete(scope.row)">删除</el-button> + <template #default="{ row }"> + <el-button type="primary" text @click="openForm('update', row)">修改</el-button> + <el-button type="primary" text @click="openForm('createChildren', row)"> 新增 </el-button> + <el-button type="danger" text @click="handleDelete(row.sourceId)">删除</el-button> </template> </el-table-column> </el-table> - <Pagination - v-model:limit="searchForm.pageSize" - v-model:page="searchForm.pageNum" - :total="total" - @pagination="handleQuery" - /> <DialogSource ref="sourceDialog" @success="handleQuery" /> </div> </template> <script setup name="ClueSource"> +import { handleTree } from '@/utils/tree' +import * as SourceApi from '@/api/clue/source' +import { dateFormatter } from '@/utils/formatTime' import DialogSource from './DialogSource.vue' +import { DICT_TYPE } from '@/utils/dict' + +const message = useMessage() // 消息弹窗 +const { t } = useI18n() // 国际化 const searchForm = ref({ - pageNum: 1, - pageSize: 20 + sourceName: undefined }) -const total = ref(0) const sourceDialog = ref() const tableList = ref([]) const loading = ref(false) function handleQuery() { - searchForm.value.pageNum = 1 getList() } function resetQuery() { searchForm.value = { - question: '', - pageSize: 20, - pageNum: 1 + sourceName: '' } getList() } -function getList() { - tableList.value = [ - { - sourceId: 1, - sourceName: '测试', - level: 1, - children: [{ sourceId: 1001, sourceName: '二级来源', level: 2, parentSource: '测试' }] - } - ] +async function getList() { + loading.value = true + try { + const data = await SourceApi.getSourcePage(searchForm.value) + tableList.value = handleTree(data, 'sourceId') + } finally { + loading.value = false + } } function openForm(type, info) { sourceDialog.value.open(type, info) } -async function handleDelete(row) { +async function handleDelete(id) { try { - console.log(row) // 删除的二次确认 await message.delConfirm() // 发起删除 - // await UserApi.deleteUser(row.id) + await SourceApi.deleteSource(id) message.success(t('common.delSuccess')) // 刷新列表 await getList() } catch {} } + +onMounted(() => { + getList() +}) </script> <style lang="scss" scoped></style> diff --git a/src/views/Clue/Set/Comp/DialogSource.vue b/src/views/Clue/Set/Comp/DialogSource.vue index 524f85e..9c3c337 100644 --- a/src/views/Clue/Set/Comp/DialogSource.vue +++ b/src/views/Clue/Set/Comp/DialogSource.vue @@ -7,14 +7,20 @@ :rules="formRules" label-width="80px" > - <el-form-item v-if="formData.level > 1" label="上级来源"> + <el-form-item v-if="formData.parentSource" label="上级来源"> <el-input v-model="formData.parentSource" disabled /> </el-form-item> <el-form-item label="来源名称" prop="sourceName"> <el-input v-model="formData.sourceName" placeholder="请输入来源名称" /> </el-form-item> - <el-form-item label="排序" prop="orderNum"> - <el-input v-model="formData.orderNum" placeholder="请输入排序" type="number" :min="0" /> + <el-form-item label="排序" prop="sort"> + <el-input v-model="formData.sort" placeholder="请输入排序" type="number" :min="0" /> + </el-form-item> + <el-form-item label="状态" prop="status"> + <el-radio-group v-model="formData.status"> + <el-radio :label="0"> 启用 </el-radio> + <el-radio :label="1"> 禁用 </el-radio> + </el-radio-group> </el-form-item> <el-form-item label="备注" prop="remark"> <el-input @@ -32,6 +38,8 @@ </Dialog> </template> <script name="DialogSource" setup> +import * as SourceApi from '@/api/clue/source' + const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 @@ -41,7 +49,7 @@ const formLoading = ref(false) // 表单的加载中:1)修改时的数据加 const formType = ref('') // 表单的类型:create - 新增;update - 修改 const formData = ref({ sourceName: '', - orderNum: 1, + sort: 1, remark: '' }) const formRules = reactive({ @@ -56,16 +64,15 @@ const open = async (type, info) => { formType.value = type resetForm() // 修改时,设置数据 - if (info.sourceId) { + if (info?.sourceId) { formLoading.value = true try { if (type == 'update') { - formData.value = { ...info } + formData.value = await SourceApi.getSource(info.sourceId) } else { - formData.value.level = info.level + 1 formData.value.parentSource = info.sourceName + formData.value.parentId = info.sourceId } - // formData.value = await UserApi.getUser(id) } finally { formLoading.value = false } @@ -83,13 +90,12 @@ const submitForm = async () => { // 提交请求 formLoading.value = true try { - // const data = formData.value as unknown as UserApi.UserVO - if (formType.value === 'create') { - // await UserApi.createUser(data) - message.success(t('common.createSuccess')) - } else { - // await UserApi.updateUser(data) + if (formType.value === 'update') { + await SourceApi.updateSource(formData.value) message.success(t('common.updateSuccess')) + } else { + await SourceApi.createSource(formData.value) + message.success(t('common.createSuccess')) } dialogVisible.value = false // 发送操作成功的事件 @@ -103,7 +109,8 @@ const submitForm = async () => { const resetForm = () => { formData.value = { sourceName: '', - orderNum: 1, + status: 0, + sort: 1, remark: '' } formRef.value?.resetFields() diff --git a/src/views/Clue/Set/Comp/FieldClue.vue b/src/views/Clue/Set/Comp/FieldClue.vue index 4e4ebfd..625fb17 100644 --- a/src/views/Clue/Set/Comp/FieldClue.vue +++ b/src/views/Clue/Set/Comp/FieldClue.vue @@ -2,45 +2,55 @@ <el-row :gutter="80"> <el-col :span="10" :offset="0"> <el-button class="mb-10px" type="primary" @click="handleInsert">新增属性</el-button> - <el-table :data="tableList"> - <el-table-column prop="name" label="名称" /> - <el-table-column label="启用状态"> + <el-table :data="tableList" :row-class-name="setRowClass" @row-click="handleRowClick"> + <el-table-column prop="label" label="名称" /> + <el-table-column prop="field" label="属性编码" /> + <el-table-column prop="component" label="类型" width="200px"> + <template #default="{ row }"> + {{ typeOptions.find((it) => it.value == row.component).label }} + </template> + </el-table-column> + <el-table-column label="启用状态" width="100"> <template #default="{ row }"> <el-switch v-model="row.status" - :active-value="1" - :inactive-value="0" - :disabled="!row.canUpdate" + :active-value="0" + :inactive-value="1" @change="changeStatus(row)" /> </template> </el-table-column> <el-table-column label="操作" width="80px"> <template #default="{ row }"> - <el-button - type="primary" - text - :disabled="!row.canUpdate" - style="padding: 0" - @click="remove(row)" + <el-button type="primary" text style="padding: 0" @click="remove(row.clueParamId)" >删除</el-button > </template> </el-table-column> </el-table> </el-col> - <el-col :span="14" :offset="0"> - <el-form :model="form" ref="fieldForm" :rules="rules" label-width="80px" :inline="false"> - <el-form-item label="属性名称" prop="name"> - <el-input v-model="form.name" placeholder="请输入属性名称" /> + <el-col :span="14" :offset="0" v-if="tableList.length || formType == 'create'"> + <el-form :model="form" ref="fieldForm" :rules="rules" label-width="100px" :inline="false"> + <el-form-item label="属性名称" prop="label"> + <el-input v-model="form.label" placeholder="请输入属性名称" /> + </el-form-item> + <el-form-item prop="field"> + <template #label> + <div class="flex justify-center" style="align-items: center"> + <span>属性编码</span> + <Tooltip message="请输入字母或数字,必须以字母开头" /> + </div> + </template> + <el-input v-model="form.field" placeholder="请输入属性编码" /> </el-form-item> - <el-form-item label="属性类型" prop="type"> + <el-form-item label="属性类型" prop="component"> <el-select - v-model="form.type" + v-model="form.component" placeholder="请选择属性类型" clearable filterable style="width: 100%" + @change="form.options = []" > <el-option v-for="item in typeOptions" @@ -51,72 +61,174 @@ </el-select> </el-form-item> <el-form-item - v-if="['Checkbox', 'Radio', 'Select'].includes(form.type)" + v-if="['Checkbox', 'Radio', 'Select'].includes(form.component)" label="选项" - prop="option" - key="option" + prop="options" + key="options" > <div> - <el-button type="primary" @click="optionList.push([])"> 新增选项 </el-button> + <el-button type="primary" @click="handleAddOption"> 新增选项 </el-button> <div class="flex justify-between mt-10px" - v-for="(item, index) in optionList" + v-for="(item, index) in form.options" :key="index" > - <el-input v-model="item.label" placeholder="请输入选项内容" clearable /> - <el-button type="primary" text @click="optionList.splice(index, 1)">删除</el-button> + <el-input + v-model="item.name" + placeholder="请输入选项内容" + clearable + style="width: 300px !important" + @blur="item.id = item.name" + /> + <el-button type="primary" text @click="form.options.splice(index, 1)">删除</el-button> </div> </div> </el-form-item> <el-form-item> - <el-button type="primary" @click="onSubmit">保存</el-button> + <el-button type="primary" :disabled="formLoading" @click="onSubmit">保存</el-button> </el-form-item> </el-form> </el-col> </el-row> </template> -<script setup> -const tableList = ref([{ name: '咨询车型', status: 0, canUpdate: false }]) +<script setup name="FieldClue"> +import * as FieldApi from '@/api/clue/clueField' +import { getDictOptions } from '@/utils/dict' + +const message = useMessage() // 消息弹窗 +const { t } = useI18n() // 国际化 + +const tableList = ref([]) +const currentRowId = ref('') + +function setRowClass({ row }) { + return row.field == currentRowId.value ? 'current-row' : '' +} + +function handleRowClick(row) { + formType.value = 'update' + currentRowId.value = row.field + form.value = { ...row } +} const form = ref({ - name: undefined, - type: undefined, - option: undefined + label: undefined, + field: '', + component: undefined, + options: [], + status: 0, + isCustom: true, + isForm: true, + isSearch: true, + isTable: true }) -const typeOptions = ref([ - { label: '输入框', value: 'Input' }, - { label: '多选', value: 'Checkbox' }, - { label: '单选', value: 'Radio' }, - { label: '下拉选', value: 'Select' }, - { label: '开关', value: 'Switch' }, - { label: '日期选择', value: 'DatePicker' }, - { label: '时间选择', value: 'TimePicker' }, - { label: '富文本', value: 'Editor' }, - { label: '图片', value: 'UploadImg' }, - { label: '文件', value: 'UploadFile' } -]) +const loading = ref(false) + +const typeOptions = ref([]) -const rules = {} +const rules = { + label: { required: true, message: '名称不可为空', trigger: 'blur' }, + field: { required: true, message: '编码不可为空', trigger: 'blur' }, + component: { required: true, message: '类型不可为空', trigger: 'change' } +} + +async function getList() { + loading.value = true + try { + const data = await FieldApi.getDiyFieldList() + tableList.value = data + if (data.length) { + handleRowClick(data[0]) + } + } finally { + loading.value = false + } +} -const optionList = ref([]) +const formType = ref('') function handleInsert() { - console.log('新增') + formType.value = 'create' + form.value = { + label: undefined, + field: '', + component: undefined, + options: [], + status: 0, + isCustom: true, + isForm: true, + isSearch: true, + isTable: true + } } -function changeStatus(row) { - console.log(row.status) +async function remove(id) { + try { + // 删除的二次确认 + await message.delConfirm() + // 发起删除 + await FieldApi.deleteField(id) + message.success(t('common.delSuccess')) + // 刷新列表 + await getList() + } catch (err) { + console.log(err) + } } -function remove(row) { - console.log(row.status) +async function changeStatus(row) { + try { + // 二次确认 + await message.confirm('是否确认修改状态') + await FieldApi.updateFieldStatus(row.clueParamId, row.status) + message.success('修改成功') + // 刷新列表 + await getList() + } catch { + // 取消后,进行恢复按钮 + row.status = row.status == 0 ? 1 : 0 + } } -function onSubmit() { - console.log('保存') +const fieldForm = ref() +const formLoading = ref(false) + +function handleAddOption() { + if (form.value.options) { + form.value.options.push({}) + } else { + form.value.options = [] + } +} + +async function onSubmit() { + // 校验表单 + if (!fieldForm.value) return + const valid = await fieldForm.value.validate() + if (!valid) return + // 提交请求 + formLoading.value = true + try { + if (formType.value === 'create') { + await FieldApi.createField(form.value) + message.success(t('common.createSuccess')) + } else { + await FieldApi.updateField(form.value) + message.success(t('common.updateSuccess')) + } + // 发送操作成功的事件 + getList() + } finally { + formLoading.value = false + } } + +onMounted(() => { + typeOptions.value = getDictOptions('attribute_type') + getList() +}) </script> <style lang="scss" scoped></style> diff --git a/src/views/Clue/Set/Comp/FieldOrder.vue b/src/views/Clue/Set/Comp/FieldOrder.vue index dae2103..2a8dbf9 100644 --- a/src/views/Clue/Set/Comp/FieldOrder.vue +++ b/src/views/Clue/Set/Comp/FieldOrder.vue @@ -2,45 +2,55 @@ <el-row :gutter="80"> <el-col :span="10" :offset="0"> <el-button class="mb-10px" type="primary" @click="handleInsert">新增属性</el-button> - <el-table :data="tableList"> - <el-table-column prop="name" label="名称" /> - <el-table-column label="启用状态"> + <el-table :data="tableList" :row-class-name="setRowClass" @row-click="handleRowClick"> + <el-table-column prop="label" label="名称" /> + <el-table-column prop="field" label="属性编码" /> + <el-table-column prop="component" label="类型" width="200px"> + <template #default="{ row }"> + {{ typeOptions.find((it) => it.value == row.component).label }} + </template> + </el-table-column> + <el-table-column label="启用状态" width="100"> <template #default="{ row }"> <el-switch v-model="row.status" - :active-value="1" - :inactive-value="0" - :disabled="!row.canUpdate" + :active-value="0" + :inactive-value="1" @change="changeStatus(row)" /> </template> </el-table-column> <el-table-column label="操作" width="80px"> <template #default="{ row }"> - <el-button - type="primary" - text - :disabled="!row.canUpdate" - style="padding: 0" - @click="remove(row)" + <el-button type="primary" text style="padding: 0" @click="remove(row.clueParamId)" >删除</el-button > </template> </el-table-column> </el-table> </el-col> - <el-col :span="14" :offset="0"> - <el-form :model="form" ref="fieldForm" :rules="rules" label-width="80px" :inline="false"> - <el-form-item label="属性名称" prop="name"> - <el-input v-model="form.name" placeholder="请输入属性名称" /> + <el-col :span="14" :offset="0" v-if="tableList.length || formType == 'create'"> + <el-form :model="form" ref="fieldForm" :rules="rules" label-width="100px" :inline="false"> + <el-form-item label="属性名称" prop="label"> + <el-input v-model="form.label" placeholder="请输入属性名称" /> + </el-form-item> + <el-form-item prop="field"> + <template #label> + <div class="flex justify-center" style="align-items: center"> + <span>属性编码</span> + <Tooltip message="请输入字母或数字,必须以字母开头" /> + </div> + </template> + <el-input v-model="form.field" placeholder="请输入属性编码" /> </el-form-item> - <el-form-item label="属性类型" prop="type"> + <el-form-item label="属性类型" prop="component"> <el-select - v-model="form.type" + v-model="form.component" placeholder="请选择属性类型" clearable filterable style="width: 100%" + @change="form.options = []" > <el-option v-for="item in typeOptions" @@ -51,72 +61,174 @@ </el-select> </el-form-item> <el-form-item - v-if="['Checkbox', 'Radio', 'Select'].includes(form.type)" + v-if="['Checkbox', 'Radio', 'Select'].includes(form.component)" label="选项" - prop="option" - key="option" + prop="options" + key="options" > <div> - <el-button type="primary" @click="optionList.push([])"> 新增选项 </el-button> + <el-button type="primary" @click="handleAddOption"> 新增选项 </el-button> <div class="flex justify-between mt-10px" - v-for="(item, index) in optionList" + v-for="(item, index) in form.options" :key="index" > - <el-input v-model="item.label" placeholder="请输入选项内容" clearable /> - <el-button type="primary" text @click="optionList.splice(index, 1)">删除</el-button> + <el-input + v-model="item.name" + placeholder="请输入选项内容" + clearable + style="width: 300px !important" + @blur="item.id = item.name" + /> + <el-button type="primary" text @click="form.options.splice(index, 1)">删除</el-button> </div> </div> </el-form-item> <el-form-item> - <el-button type="primary" @click="onSubmit">保存</el-button> + <el-button type="primary" :disabled="formLoading" @click="onSubmit">保存</el-button> </el-form-item> </el-form> </el-col> </el-row> </template> -<script setup> -const tableList = ref([{ name: '额外支出费用', status: 1, canUpdate: true }]) +<script setup name="FieldOrder"> +import * as FieldApi from '@/api/clue/orderField.js' +import { getDictOptions } from '@/utils/dict' + +const message = useMessage() // 消息弹窗 +const { t } = useI18n() // 国际化 + +const tableList = ref([]) +const currentRowId = ref('') + +function setRowClass({ row }) { + return row.field == currentRowId.value ? 'current-row' : '' +} + +function handleRowClick(row) { + formType.value = 'update' + currentRowId.value = row.field + form.value = { ...row } +} const form = ref({ - name: undefined, - type: undefined, - option: undefined + label: undefined, + field: '', + component: undefined, + options: [], + status: 0, + isCustom: true, + isForm: true, + isSearch: true, + isTable: true }) -const typeOptions = ref([ - { label: '输入框', value: 'Input' }, - { label: '多选', value: 'Checkbox' }, - { label: '单选', value: 'Radio' }, - { label: '下拉选', value: 'Select' }, - { label: '开关', value: 'Switch' }, - { label: '日期选择', value: 'DatePicker' }, - { label: '时间选择', value: 'TimePicker' }, - { label: '富文本', value: 'Editor' }, - { label: '图片', value: 'UploadImg' }, - { label: '文件', value: 'UploadFile' } -]) +const loading = ref(false) + +const typeOptions = ref([]) -const rules = {} +const rules = { + label: { required: true, message: '名称不可为空', trigger: 'blur' }, + field: { required: true, message: '编码不可为空', trigger: 'blur' }, + component: { required: true, message: '类型不可为空', trigger: 'change' } +} + +async function getList() { + loading.value = true + try { + const data = await FieldApi.getDiyFieldList() + tableList.value = data + if (data.length) { + handleRowClick(data[0]) + } + } finally { + loading.value = false + } +} -const optionList = ref([]) +const formType = ref('') function handleInsert() { - console.log('新增') + formType.value = 'create' + form.value = { + label: undefined, + field: '', + component: undefined, + options: [], + status: 0, + isCustom: true, + isForm: true, + isSearch: true, + isTable: true + } } -function changeStatus(row) { - console.log(row.status) +async function remove(id) { + try { + // 删除的二次确认 + await message.delConfirm() + // 发起删除 + await FieldApi.deleteField(id) + message.success(t('common.delSuccess')) + // 刷新列表 + await getList() + } catch (err) { + console.log(err) + } } -function remove(row) { - console.log(row.status) +async function changeStatus(row) { + try { + // 二次确认 + await message.confirm('是否确认修改状态') + await FieldApi.updateFieldStatus(row.clueParamId, row.status) + message.success('修改成功') + // 刷新列表 + await getList() + } catch { + // 取消后,进行恢复按钮 + row.status = row.status == 0 ? 1 : 0 + } } -function onSubmit() { - console.log('保存') +const fieldForm = ref() +const formLoading = ref(false) + +function handleAddOption() { + if (form.value.options) { + form.value.options.push({}) + } else { + form.value.options = [] + } +} + +async function onSubmit() { + // 校验表单 + if (!fieldForm.value) return + const valid = await fieldForm.value.validate() + if (!valid) return + // 提交请求 + formLoading.value = true + try { + if (formType.value === 'create') { + await FieldApi.createField(form.value) + message.success(t('common.createSuccess')) + } else { + await FieldApi.updateField(form.value) + message.success(t('common.updateSuccess')) + } + // 发送操作成功的事件 + getList() + } finally { + formLoading.value = false + } } + +onMounted(() => { + typeOptions.value = getDictOptions('attribute_type') + getList() +}) </script> <style lang="scss" scoped></style> diff --git a/src/views/Clue/Set/index.vue b/src/views/Clue/Set/index.vue index f50f702..9718b0d 100644 --- a/src/views/Clue/Set/index.vue +++ b/src/views/Clue/Set/index.vue @@ -1,26 +1,34 @@ <template> <div> <el-tabs v-model="tabIndex" type="border-card"> - <el-tab-pane label="线索属性" :name="0"> - <FieldClue /> + <el-tab-pane label="线索属性" :name="0" v-if="checkPermi(['clue:setting:clue-props'])"> + <FieldClue v-if="tabIndex == 0" /> </el-tab-pane> - <el-tab-pane label="成交属性" :name="10"> - <FieldOrder /> + <el-tab-pane label="成交属性" :name="10" v-if="checkPermi(['clue:setting:order-props'])"> + <FieldOrder v-if="tabIndex == 10" /> </el-tab-pane> - <el-tab-pane label="线索来源" :name="15"> - <ClueSource /> + <el-tab-pane label="线索来源" :name="15" v-if="checkPermi(['clue:setting:clue-resource'])"> + <ClueSource v-if="tabIndex == 15" /> </el-tab-pane> - <el-tab-pane label="线索获取规则" :name="20"> - <ClueGet /> + <!-- <el-tab-pane + label="线索获取规则" + :name="20" + v-if="checkPermi(['clue:setting:clue-get-rules'])" + > + <ClueGet v-if="tabIndex == 20" /> + </el-tab-pane> --> + <!-- <el-tab-pane + label="线索分配规则" + :name="30" + v-if="checkPermi(['clue:setting:clue-send-rules'])" + > + <ClueSend v-if="tabIndex == 30" /> + </el-tab-pane> --> + <el-tab-pane label="常规设置" :name="40" v-if="checkPermi(['clue:setting:general-setting'])"> + <GeneralSet v-if="tabIndex == 40" /> </el-tab-pane> - <el-tab-pane label="线索分配规则" :name="30"> - <ClueSend /> - </el-tab-pane> - <el-tab-pane label="常规设置" :name="40"> - <GeneralSet /> - </el-tab-pane> - <el-tab-pane label="消息通知" :name="50"> - <MsgSend /> + <el-tab-pane label="消息通知" :name="50" v-if="checkPermi(['mall:setting:prod'])"> + <MsgSend v-if="tabIndex == 50" /> </el-tab-pane> </el-tabs> </div> @@ -30,10 +38,11 @@ import FieldClue from './Comp/FieldClue.vue' import FieldOrder from './Comp/FieldOrder.vue' import ClueSource from './Comp/ClueSource.vue' -import ClueGet from './Comp/ClueGet.vue' -import ClueSend from './Comp/ClueSend.vue' +// import ClueGet from './Comp/ClueGet.vue' +// import ClueSend from './Comp/ClueSend.vue' import MsgSend from './Comp/MsgSend.vue' import GeneralSet from './Comp/GeneralSet.vue' +import { checkPermi } from '@/utils/permission' const tabIndex = ref(0) </script> diff --git a/src/views/Clue/Skill/index.vue b/src/views/Clue/Skill/index.vue index f2c2a55..927e23f 100644 --- a/src/views/Clue/Skill/index.vue +++ b/src/views/Clue/Skill/index.vue @@ -11,9 +11,13 @@ /> </el-form-item> <el-form-item> - <el-button type="primary" @click="handleQuery">搜索</el-button> - <el-button @click="resetQuery">重置</el-button> - <el-button type="primary" plain @click="handleAdd">新增</el-button> + <el-button type="primary" @click="handleQuery" v-hasPermi="['clue:skill:search']"> + 搜索 + </el-button> + <el-button @click="resetQuery" v-hasPermi="['clue:skill:reset']">重置</el-button> + <el-button type="primary" plain @click="handleAdd" v-hasPermi="['clue:skill:add']"> + 新增 + </el-button> </el-form-item> </el-form> <el-table :data="tableList"> @@ -27,8 +31,22 @@ <el-table-column label="关键词" align="center" prop="skillKey" /> <el-table-column label="操作" align="center"> <template #default="scope"> - <el-button type="primary" text @click="handleUpdate(scope.row)">修改</el-button> - <el-button type="primary" text @click="handleDelete(scope.row)">删除</el-button> + <el-button + type="primary" + text + @click="handleUpdate(scope.row)" + v-hasPermi="['clue:skill:update']" + > + 修改 + </el-button> + <el-button + type="primary" + text + @click="handleDelete(scope.row)" + v-hasPermi="['clue:skill:delete']" + > + 删除 + </el-button> </template> </el-table-column> </el-table> diff --git a/src/views/MiniMall/Inventory/Comp/InventoryRecord.vue b/src/views/MiniMall/Inventory/Comp/InventoryRecord.vue index 5d458e8..fb42853 100644 --- a/src/views/MiniMall/Inventory/Comp/InventoryRecord.vue +++ b/src/views/MiniMall/Inventory/Comp/InventoryRecord.vue @@ -51,8 +51,8 @@ <el-table class="mt-20px" :data="tableList" border> <el-table-column type="index" width="50px" /> - <el-table-column prop="" label="产品名称" /> - <el-table-column prop="" label="规格" /> + <el-table-column prop="productName" label="产品名称" /> + <el-table-column prop="specsName" label="规格" /> <el-table-column label="变动类型"> <template #default="{ row }"> {{ ['', '入库', '出库'][row.changeType] }} @@ -61,8 +61,8 @@ <el-table-column prop="num" label="数量" /> <el-table-column prop="money" label="金额" /> <el-table-column prop="changeTime" label="变动时间" :formatter="dateFormatter" /> - <el-table-column prop="changeUser" label="变动人员" /> - <el-table-column prop="" label="所属仓库" /> + <el-table-column prop="changeUserName" label="变动人员" /> + <el-table-column prop="warehouseName" label="所属仓库" /> <el-table-column prop="remark" label="备注" /> </el-table> <Pagination diff --git a/src/views/MiniMall/Inventory/Comp/Warehouse.vue b/src/views/MiniMall/Inventory/Comp/Warehouse.vue index e5c78b6..d667f8f 100644 --- a/src/views/MiniMall/Inventory/Comp/Warehouse.vue +++ b/src/views/MiniMall/Inventory/Comp/Warehouse.vue @@ -25,12 +25,19 @@ <el-button type="primary" style="padding: 0" + :disabled="row.type == 1" text @click="openForm('update', row.warehouseId)" > 修改 </el-button> - <el-button type="danger" style="padding: 0" text @click="handleRemove(row.warehouseId)"> + <el-button + type="danger" + style="padding: 0" + :disabled="row.type == 1" + text + @click="handleRemove(row.warehouseId)" + > 删除 </el-button> </template>