(Update API paths, adjust configurations, and optimize user and order management functions)
This commit is contained in:
parent
0a737b7b4b
commit
e1cd4da7dd
|
@ -6,13 +6,21 @@
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="订单搜索">
|
<el-form-item label="订单搜索">
|
||||||
<el-input v-model="queryParams.keyword" clearable placeholder="请输入店员名称" />
|
<el-input v-model="queryParams.keyword" clearable placeholder="请输入流水号/用户昵称 " />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="店员">
|
||||||
|
<el-select class="flex-1" v-model="queryParams.staff_id" placeholder="请选择店员">
|
||||||
|
<el-option :label="item.staff_name" :value="item.id"
|
||||||
|
v-for="(item, index) in staffList" />
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="resetPage">查询</el-button>
|
<el-button type="primary" @click="resetPage">查询</el-button>
|
||||||
<el-button @click="resetParams">重置</el-button>
|
<el-button @click="handResetParams">重置</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
@ -41,6 +49,8 @@
|
||||||
import Popup from '@/components/popup/index.vue'
|
import Popup from '@/components/popup/index.vue'
|
||||||
import { usePaging } from '@/hooks/usePaging'
|
import { usePaging } from '@/hooks/usePaging'
|
||||||
import { apiStoreBillDetail } from '@/api/store_finance_flow.ts'
|
import { apiStoreBillDetail } from '@/api/store_finance_flow.ts'
|
||||||
|
import { apiStaffLists } from '@/api/goodsList.ts'
|
||||||
|
import { reactive } from 'vue';
|
||||||
|
|
||||||
|
|
||||||
const emit = defineEmits(['success', 'close'])
|
const emit = defineEmits(['success', 'close'])
|
||||||
|
@ -52,21 +62,26 @@ const popupTitle = computed(() => {
|
||||||
return '账单详情'
|
return '账单详情'
|
||||||
})
|
})
|
||||||
|
|
||||||
let queryParams = {
|
let queryParams = reactive({
|
||||||
id: "",
|
id: "",
|
||||||
keyword: "",
|
keyword: "",
|
||||||
date_type: "",
|
date_type: "",
|
||||||
date: "",
|
date: "",
|
||||||
staff_id: "",
|
staff_id: "",
|
||||||
|
|
||||||
}
|
})
|
||||||
|
|
||||||
const { pager, getLists, resetParams, resetPage } = usePaging({
|
const { pager, getLists, resetParams, resetPage } = usePaging({
|
||||||
fetchFun: apiStoreBillDetail,
|
fetchFun: apiStoreBillDetail,
|
||||||
params: queryParams
|
params: queryParams
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const handResetParams = () => {
|
||||||
|
queryParams.keyword = ''
|
||||||
|
queryParams.staff_id = ''
|
||||||
|
getLists()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 提交按钮
|
// 提交按钮
|
||||||
|
@ -82,9 +97,6 @@ const open = (data: any) => {
|
||||||
data.year + '-W' + data.week
|
data.year + '-W' + data.week
|
||||||
:
|
:
|
||||||
data.time
|
data.time
|
||||||
|
|
||||||
console.log(queryParams)
|
|
||||||
// queryParams.id = id
|
|
||||||
popupRef.value?.open()
|
popupRef.value?.open()
|
||||||
getLists()
|
getLists()
|
||||||
}
|
}
|
||||||
|
@ -98,4 +110,11 @@ const handleClose = () => {
|
||||||
defineExpose({
|
defineExpose({
|
||||||
open,
|
open,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const staffList = ref([])
|
||||||
|
const getStaffList = async () => {
|
||||||
|
let res = await apiStaffLists({ page_no: 1, page_size: 100 })
|
||||||
|
staffList.value = res.lists
|
||||||
|
}
|
||||||
|
getStaffList()
|
||||||
</script>
|
</script>
|
|
@ -51,7 +51,7 @@
|
||||||
<el-table-column label="操作" width="170" fixed="right">
|
<el-table-column label="操作" width="170" fixed="right">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button @click="handleDetail(row)" link type="primary">详情</el-button>
|
<el-button @click="handleDetail(row)" link type="primary">详情</el-button>
|
||||||
<el-button @click="handleDownlon(row)" link type="primary">下载</el-button>
|
<!-- <el-button @click="handleDownlon(row)" link type="primary">下载</el-button> -->
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
@ -114,16 +114,12 @@ const handleDetail = async (row) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const handleDownlon = (row) => {
|
const handleDownlon = async (row) => {
|
||||||
|
let res = await apiStoreBillDownload({ id: row.id })
|
||||||
const a = document.createElement('a')
|
const a = document.createElement('a')
|
||||||
a.href = 'https://multi-store.crmeb.net/store/bill/index'
|
a.href = 'https://multi-store.crmeb.net/store/bill/index'
|
||||||
a.click()
|
a.click()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
getLists()
|
getLists()
|
||||||
</script>
|
</script>
|
|
@ -1,31 +0,0 @@
|
||||||
<template>
|
|
||||||
<!-- <el-table :data="props.lists"> -->
|
|
||||||
<el-table :data="[{}]">
|
|
||||||
<el-table-column :label="item.label" :prop="item.prop" show-overflow-tooltip v-for="item in column" />
|
|
||||||
</el-table>
|
|
||||||
<div class="flex mt-4 justify-end">
|
|
||||||
<pagination v-model="pager" @change="getLists" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup name="manageProjectLists">
|
|
||||||
import { ref, reactive, defineProps } from "vue"
|
|
||||||
import { usePaging } from '@/hooks/usePaging'
|
|
||||||
let props = defineProps({
|
|
||||||
fetchApi: {
|
|
||||||
type: Function
|
|
||||||
},
|
|
||||||
column: {
|
|
||||||
type: Array,
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 分页相关
|
|
||||||
const { pager, getLists, resetParams, resetPage } = usePaging({
|
|
||||||
fetchFun: props.fetchApi,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// getLists()
|
|
||||||
</script>
|
|
|
@ -1,71 +0,0 @@
|
||||||
<template>
|
|
||||||
<popup ref="popupRef" title="店员详情" :async="true" width="50vw" @close="close" :show-footer="false">
|
|
||||||
<div class="flex">
|
|
||||||
<el-avatar shape="circle" :size="70"
|
|
||||||
src="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png" />
|
|
||||||
<el-row class="w-[100%] ml-4">
|
|
||||||
<el-col :span="24">你干嘛</el-col>
|
|
||||||
<el-col :span="7">收银订单:¥200.00</el-col>
|
|
||||||
<el-col :span="7">核销订单:¥200.00</el-col>
|
|
||||||
<el-col :span="7">配送订单:¥200.00</el-col>
|
|
||||||
</el-row>
|
|
||||||
</div>
|
|
||||||
<el-tabs tab-position="left" style="height: 200px" class="demo-tabs mt-8">
|
|
||||||
<el-tab-pane label="收银订单">
|
|
||||||
<myTable :column="datas.moneyLists"></myTable>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="配送订单">
|
|
||||||
<myTable :column="datas.moneyLists"></myTable>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="核销订单">
|
|
||||||
<myTable :column="datas.moneyLists"></myTable>
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
</popup>
|
|
||||||
</template>
|
|
||||||
<script setup>
|
|
||||||
import { ref, reactive } from 'vue'
|
|
||||||
import myTable from './components/myTable.vue';
|
|
||||||
|
|
||||||
|
|
||||||
const popupRef = ref(null)
|
|
||||||
const emit = defineEmits(['close'])
|
|
||||||
|
|
||||||
const open = () => {
|
|
||||||
popupRef.value?.open()
|
|
||||||
}
|
|
||||||
const close = () => {
|
|
||||||
emit('close')
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const datas = reactive({
|
|
||||||
moneyLists: [
|
|
||||||
{ label: '订单id', prop: 'orderid' },
|
|
||||||
{ label: '收货人', prop: 'orderid' },
|
|
||||||
{ label: '商品数量', prop: 'orderid' },
|
|
||||||
{ label: '商品总价', prop: 'orderid' },
|
|
||||||
{ label: '实付金额', prop: 'orderid' },
|
|
||||||
{ label: '交易完成时间', prop: 'orderid' },
|
|
||||||
],
|
|
||||||
sendLists: [
|
|
||||||
{ label: '订单id', prop: 'orderid' },
|
|
||||||
{ label: '收货人', prop: 'orderid' },
|
|
||||||
{ label: '商品数量', prop: 'orderid' },
|
|
||||||
{ label: '商品总价', prop: 'orderid' },
|
|
||||||
{ label: '实付金额', prop: 'orderid' },
|
|
||||||
{ label: '交易完成时间', prop: 'orderid' },
|
|
||||||
],
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
open,
|
|
||||||
})
|
|
||||||
</script>
|
|
|
@ -1,166 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="edit-popup">
|
|
||||||
<popup ref="popupRef" :title="popupTitle" :async="true" width="550px" @confirm="handleSubmit"
|
|
||||||
@close="handleClose">
|
|
||||||
<el-form ref="formRef" :model="formData" label-width="120px" :rules="formRules">
|
|
||||||
<el-form-item label="店员名称" prop="title">
|
|
||||||
<el-input v-model="formData.title" clearable placeholder="请输入店员名称" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="头像" prop="title">
|
|
||||||
<el-input v-model="formData.title" clearable placeholder="请输入店员名称" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="店员账号" prop="title">
|
|
||||||
<el-input v-model="formData.title" clearable placeholder="请输入店员账号" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="店员密码" prop="title">
|
|
||||||
<el-input v-model="formData.title" clearable placeholder="请输入店员账号" type="password" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="确认密码" prop="title">
|
|
||||||
<el-input v-model="formData.title" clearable placeholder="请确认账号密码" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="手机号码" prop="title">
|
|
||||||
<el-input v-model="formData.title" clearable placeholder="请输入手机号码" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="店员身份" prop="title">
|
|
||||||
<el-input v-model="formData.title" clearable placeholder="请输入手机号码" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="状态" prop="title">
|
|
||||||
<el-input v-model="formData.title" clearable placeholder="请输入手机号码" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</popup>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup name="oaPlanEdit">
|
|
||||||
import type { FormInstance } from 'element-plus'
|
|
||||||
import Popup from '@/components/popup/index.vue'
|
|
||||||
// import { apiOaPlanAdd, apiOaPlanEdit, apiOaPlanDetail } from '@/api/oa_plan'
|
|
||||||
import { timeFormat } from '@/utils/util'
|
|
||||||
import type { PropType } from 'vue'
|
|
||||||
defineProps({
|
|
||||||
dictData: {
|
|
||||||
type: Object as PropType<Record<string, any[]>>,
|
|
||||||
default: () => ({})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const emit = defineEmits(['success', 'close'])
|
|
||||||
const formRef = shallowRef<FormInstance>()
|
|
||||||
const popupRef = shallowRef<InstanceType<typeof Popup>>()
|
|
||||||
const mode = ref('add')
|
|
||||||
|
|
||||||
|
|
||||||
// 弹窗标题
|
|
||||||
const popupTitle = computed(() => {
|
|
||||||
return mode.value == 'edit' ? '编辑日程安排' : '新增日程安排'
|
|
||||||
})
|
|
||||||
|
|
||||||
// 表单数据
|
|
||||||
const formData = reactive({
|
|
||||||
id: '',
|
|
||||||
title: '',
|
|
||||||
type: '',
|
|
||||||
start_time: '',
|
|
||||||
end_time: '',
|
|
||||||
remind_type: '',
|
|
||||||
remark: '',
|
|
||||||
})
|
|
||||||
|
|
||||||
const chekcDate = (rule: any, value: any, callback: any) => {
|
|
||||||
if (new Date(formData.end_time) < new Date(formData.start_time)) {
|
|
||||||
callback(new Error('结束时间不能早于开始时间'))
|
|
||||||
} else {
|
|
||||||
callback()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 表单验证
|
|
||||||
const formRules = reactive<any>({
|
|
||||||
title: [{
|
|
||||||
required: true,
|
|
||||||
message: '请输入工作安排主题',
|
|
||||||
trigger: ['blur']
|
|
||||||
}],
|
|
||||||
type: [{
|
|
||||||
required: true,
|
|
||||||
message: '请输入日程优先级',
|
|
||||||
trigger: ['blur']
|
|
||||||
}],
|
|
||||||
start_time: [{
|
|
||||||
required: true,
|
|
||||||
message: '请输入开始时间',
|
|
||||||
trigger: ['blur']
|
|
||||||
}],
|
|
||||||
end_time: [{
|
|
||||||
required: true,
|
|
||||||
message: '请输入结束时间',
|
|
||||||
trigger: ['blur']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
validator: chekcDate,
|
|
||||||
trigger: ['blur']
|
|
||||||
}],
|
|
||||||
remind_type: [{
|
|
||||||
required: true,
|
|
||||||
message: '请输入提醒类型',
|
|
||||||
trigger: ['blur']
|
|
||||||
}],
|
|
||||||
remind_time: [{
|
|
||||||
required: true,
|
|
||||||
message: '请输入提醒时间',
|
|
||||||
trigger: ['blur']
|
|
||||||
}]
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// 获取详情
|
|
||||||
const setFormData = async (data: Record<any, any>) => {
|
|
||||||
for (const key in formData) {
|
|
||||||
if (data[key] != null && data[key] != undefined) {
|
|
||||||
//@ts-ignore
|
|
||||||
formData[key] = data[key]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const getDetail = async (row: Record<string, any>) => {
|
|
||||||
const data = await apiOaPlanDetail({
|
|
||||||
id: row.id
|
|
||||||
})
|
|
||||||
setFormData(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 提交按钮
|
|
||||||
const handleSubmit = async () => {
|
|
||||||
await formRef.value?.validate()
|
|
||||||
const data = { ...formData, }
|
|
||||||
// mode.value == 'edit'
|
|
||||||
// ? await apiOaPlanEdit(data)
|
|
||||||
// : await apiOaPlanAdd(data)
|
|
||||||
popupRef.value?.close()
|
|
||||||
emit('success')
|
|
||||||
}
|
|
||||||
|
|
||||||
//打开弹窗
|
|
||||||
const open = (type = 'add', start_time = '') => {
|
|
||||||
mode.value = type
|
|
||||||
formData.start_time = start_time
|
|
||||||
popupRef.value?.open()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关闭回调
|
|
||||||
const handleClose = () => {
|
|
||||||
emit('close')
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
open,
|
|
||||||
setFormData,
|
|
||||||
getDetail
|
|
||||||
})
|
|
||||||
</script>
|
|
|
@ -1,151 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<el-card class="!border-none mb-4" shadow="never">
|
|
||||||
<el-form class="mb-[-16px]" :model="queryParams" label-width="80px">
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="6">
|
|
||||||
<el-form-item label="商品状态">
|
|
||||||
<el-select class="flex-1" v-model="queryParams.status" clearable placeholder="请选择商品状态">
|
|
||||||
<el-option label="销售中" :value="0" />
|
|
||||||
<el-option label="仓库中" :value="0" />
|
|
||||||
<el-option label="已售罄" :value="0" />
|
|
||||||
<el-option label="库存预警" :value="0" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="6">
|
|
||||||
<el-form-item label="商品搜索" prop="nature">
|
|
||||||
<el-input v-model="queryParams.status" clearable placeholder="请输入商品名称" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="6">
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" @click="resetPage">查询</el-button>
|
|
||||||
<el-button @click="resetParams">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
|
||||||
</el-card>
|
|
||||||
<el-card class="!border-none" v-loading="pager.loading" shadow="never">
|
|
||||||
<el-button v-perms="['dept.dept/add']" type="primary" @click="handleAdd()">
|
|
||||||
<template #icon>
|
|
||||||
<icon name="el-icon-Plus" />
|
|
||||||
</template>
|
|
||||||
新增
|
|
||||||
</el-button>
|
|
||||||
<div class="mt-4">
|
|
||||||
<el-table :data="pager.lists" @selection-change="handleSelectionChange">
|
|
||||||
<el-table-column label="id" prop="progress" show-overflow-tooltip />
|
|
||||||
<el-table-column label="头像" prop="build_area_text" show-overflow-tooltip>
|
|
||||||
<template #default="{ row }">
|
|
||||||
<!-- <el-image style="width: 50px; height: 50px" :src="url" /> -->
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="昵称" prop="project_level_text" show-overflow-tooltip />
|
|
||||||
<el-table-column label="店员身份" prop="project_level_text" show-overflow-tooltip />
|
|
||||||
<el-table-column label="手机号" prop="total_investment" show-overflow-tooltip />
|
|
||||||
<el-table-column label="状态" prop="engineering_status_text" show-overflow-tooltip>
|
|
||||||
<template #default="{ row }">
|
|
||||||
<el-switch v-model="row.status" :active-value="1" :inactive-value="0"
|
|
||||||
@change="changeStatus(row)"></el-switch>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="操作" width="170" fixed="right">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<el-button type="primary" link @click="handleEdit(row)">
|
|
||||||
编辑
|
|
||||||
</el-button>
|
|
||||||
<el-button type="primary" link @click="handleDetail(row)">
|
|
||||||
详情
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
<div class="flex mt-4 justify-end">
|
|
||||||
<pagination v-model="pager" @change="getLists" />
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
<edit-popup v-if="showEdit" ref="editRef" @success="getLists" @close="showEdit = false" />
|
|
||||||
<DetailPopup v-if="showDetail" ref="detailRef" @close="showEdit = false" />
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup name="manageProjectLists">
|
|
||||||
import { ref, reactive } from "vue"
|
|
||||||
import { usePaging } from '@/hooks/usePaging'
|
|
||||||
import { apiGoodsListLists, apiStatus, apiGoodsTypeLists } from '@/api/goodsList'
|
|
||||||
import EditPopup from './edit.vue'
|
|
||||||
import DetailPopup from './detail.vue'
|
|
||||||
|
|
||||||
const detailRef = ref(null)
|
|
||||||
const editRef = shallowRef<InstanceType<typeof EditPopup>>()
|
|
||||||
// 是否显示编辑框
|
|
||||||
const showEdit = ref(false)
|
|
||||||
const showDetail = ref(false)
|
|
||||||
|
|
||||||
|
|
||||||
// 查询条件
|
|
||||||
const queryParams = reactive({
|
|
||||||
status: ""
|
|
||||||
})
|
|
||||||
|
|
||||||
// 选中数据
|
|
||||||
const selectData = ref<any[]>([])
|
|
||||||
|
|
||||||
// 表格选择后回调事件
|
|
||||||
const handleSelectionChange = (val: any[]) => {
|
|
||||||
selectData.value = val.map(({ id }) => id)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 上架&下架
|
|
||||||
const changeStatus = (data: any) => {
|
|
||||||
apiStatus({
|
|
||||||
// id: data.id,
|
|
||||||
// account: data.account,
|
|
||||||
// name: data.name,
|
|
||||||
// role_id: data.role_id,
|
|
||||||
// disable: data.disable,
|
|
||||||
// org_id: data.org_id,
|
|
||||||
// dept_id: data.dept_id,
|
|
||||||
// job_id: data.job_id,
|
|
||||||
// multipoint_login: data.multipoint_login
|
|
||||||
}).finally(() => {
|
|
||||||
getLists()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分页相关
|
|
||||||
const { pager, getLists, resetParams, resetPage } = usePaging({
|
|
||||||
fetchFun: apiGoodsListLists,
|
|
||||||
params: queryParams
|
|
||||||
})
|
|
||||||
|
|
||||||
// 编辑
|
|
||||||
const handleEdit = async (data: any) => {
|
|
||||||
showEdit.value = true
|
|
||||||
await nextTick()
|
|
||||||
editRef.value?.open('edit')
|
|
||||||
editRef.value?.setFormData(data)
|
|
||||||
}
|
|
||||||
// 新增
|
|
||||||
const handleAdd = async () => {
|
|
||||||
showEdit.value = true
|
|
||||||
await nextTick()
|
|
||||||
editRef.value?.open('add')
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleDetail = () => {
|
|
||||||
showDetail.value = true
|
|
||||||
nextTick(() => {
|
|
||||||
detailRef.value?.open()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
getLists()
|
|
||||||
</script>
|
|
|
@ -154,7 +154,7 @@ const pieOption = reactive(
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: 'Access From',
|
name: '',
|
||||||
type: 'pie',
|
type: 'pie',
|
||||||
radius: '50%',
|
radius: '50%',
|
||||||
data: [
|
data: [
|
|
@ -1,142 +1,128 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="workbench">
|
<el-card>
|
||||||
<el-card shadow="never" class=" !border-none">
|
<el-form class="mb-[-16px]" :model="queryParams" label-width="80px">
|
||||||
<div class="mb-6 flex justify-between items-center">
|
<el-col :span="6">
|
||||||
<span class="text-2xl">商品概况</span>
|
<el-form-item label="时间筛选">
|
||||||
<div class="flex items-center text-sm">
|
<el-date-picker v-model="date" type="daterange" range-separator="-" start-placeholder="开始时间"
|
||||||
<span class="mr-4">时间筛选: </span>
|
end-placeholder="结束时间" />
|
||||||
<el-date-picker v-model="startEndTime" type="daterange" range-separator="至" start-placeholder="开始日期"
|
</el-form-item>
|
||||||
end-placeholder="结束日期" unlink-panels :shortcuts="shortcuts" />
|
</el-col>
|
||||||
<el-button type="primary" class="ml-4" @click="getData">查询</el-button>
|
</el-form>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-wrap">
|
|
||||||
<div class="w-1/5 flex mb-6" v-for="(item, index) in basicList" :key="index">
|
|
||||||
<div class="mr-2">
|
|
||||||
<div class="rounded-full p-2" :style="{ 'background-color': colorList[index % 4] }">
|
|
||||||
<iconfont :iconName="item.icon" white className="text-6xl" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="text-info">{{ item.name }}</div>
|
|
||||||
<div class="text-6xl">{{ item.num }}</div>
|
|
||||||
<div class="text-info">环比增长: <span :class="item.percent > 0 ? 'text-success' : 'text-danger'">{{
|
|
||||||
item.percent }}%</span></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<v-charts style="height: 400px" :option="visitorOption" :autoresize="true" />
|
|
||||||
</div>
|
|
||||||
</el-card>
|
</el-card>
|
||||||
<el-card shadow="never" class="mt-4 !border-none">
|
<el-card>
|
||||||
<div class="mb-6 flex justify-between items-center">
|
<el-row>
|
||||||
<span class="text-2xl">商品排行</span>
|
<el-col :span="6" class='flex mb-7' v-for="(item, index) in statisticLists" :key="index">
|
||||||
<div class="flex items-center text-sm">
|
<img class="w-[50px] h-[50px] mr-2" :src="item.src" />
|
||||||
<span class="mr-4">时间筛选: </span>
|
<el-statistic :title="item.title" :value="item.value" />
|
||||||
<el-date-picker v-model="startEndTime" type="daterange" range-separator="至" start-placeholder="开始日期"
|
</el-col>
|
||||||
end-placeholder="结束日期" unlink-panels :shortcuts="shortcuts" />
|
</el-row>
|
||||||
<el-button type="primary" class="ml-4" @click="getData">查询</el-button>
|
</el-card>
|
||||||
</div>
|
<el-card>
|
||||||
</div>
|
<template #header>
|
||||||
<div>
|
营业趋势
|
||||||
<el-table :data="sotreList">
|
|
||||||
<el-table-column label="商品图片">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<el-image :src="row.image" fit="cover" style="width: 50px; height: 50px" />
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
<v-charts style="height: 350px" :option="visitorOption" :autoresize="true" />
|
||||||
<el-table-column label="商品名称" prop="store_name" min-width="250" />
|
</el-card>
|
||||||
<el-table-column label="游览量" prop="visit" min-width="120" />
|
<el-row>
|
||||||
<el-table-column label="访客数" prop="user" min-width="120" />
|
<el-col :span="14">
|
||||||
<el-table-column label="加购件数" prop="cart" min-width="120" />
|
<el-card class="h-[100%]">
|
||||||
<el-table-column label="下单件数" prop="orders" min-width="120" />
|
<template #header>
|
||||||
<el-table-column label="支付件数" prop="pay" min-width="120" />
|
交易数据
|
||||||
<el-table-column label="支付金额" prop="price" min-width="120" />
|
|
||||||
<el-table-column label="收藏数" prop="collect" min-width="120" />
|
|
||||||
<el-table-column label="毛利率(%)" prop="profit" min-width="120">
|
|
||||||
<template #default="{ row }">
|
|
||||||
<span>{{ row.profit }}%</span>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
<tradData></tradData>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="10">
|
||||||
|
<el-card>
|
||||||
|
<template #header>
|
||||||
|
交易类型
|
||||||
|
</template>
|
||||||
|
<v-charts style="height: 350px" :option="tradTypeOption" :autoresize="true" />
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-card>
|
||||||
|
<template #header>
|
||||||
|
配送订单统计
|
||||||
|
</template>
|
||||||
|
<v-charts style="height: 350px" :option="sendOption" :autoresize="true" />
|
||||||
|
</el-card>
|
||||||
|
|
||||||
</el-table>
|
<el-card>
|
||||||
</div>
|
<template #header>
|
||||||
|
配送订单统计
|
||||||
|
</template>
|
||||||
|
<sendData></sendData>
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup name="product">
|
<script lang="ts" setup name="manageProjectLists">
|
||||||
// import { apiGetBasic, apiGetTrend, apiGetProductRanking } from '@/api/workbench'
|
import { ref, reactive } from "vue"
|
||||||
import moment from 'moment'
|
import { getWorkbench } from '@/api/app'
|
||||||
import vCharts from 'vue-echarts'
|
import vCharts from 'vue-echarts'
|
||||||
|
import tradData from "./components/tradData.vue"
|
||||||
|
import sendData from "./components/sendData.vue"
|
||||||
|
|
||||||
const shortcuts = [
|
const src = ref('https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg')
|
||||||
{
|
const date = ref("")
|
||||||
text: '近一周',
|
|
||||||
value: () => {
|
|
||||||
const end = new Date()
|
|
||||||
const start = new Date()
|
|
||||||
start.setDate(start.getDate() - 7)
|
|
||||||
return [start, end]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '近一月',
|
|
||||||
value: () => {
|
|
||||||
const end = new Date()
|
|
||||||
const start = new Date()
|
|
||||||
start.setMonth(start.getMonth() - 1)
|
|
||||||
return [start, end]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: '近三月',
|
|
||||||
value: () => {
|
|
||||||
const end = new Date()
|
|
||||||
const start = new Date()
|
|
||||||
start.setMonth(start.getMonth() - 3)
|
|
||||||
return [start, end]
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
// 表单数据
|
|
||||||
const visitorOption: any = reactive({
|
|
||||||
|
const statisticLists = reactive([
|
||||||
|
{
|
||||||
|
src: 'https://ceshi-engineering.lihaink.cn/uploads/files/20240604/20240604171701552002039.png',
|
||||||
|
title: "核销订单金额",
|
||||||
|
value: 1000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: "https://ceshi-engineering.lihaink.cn/uploads/files/20240604/2024060417170150a511510.png",
|
||||||
|
title: "余额消费金额",
|
||||||
|
value: 1000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'https://ceshi-engineering.lihaink.cn/uploads/files/20240604/20240604171701594ff8897.png',
|
||||||
|
title: "门店收益金额",
|
||||||
|
value: 1000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'https://ceshi-engineering.lihaink.cn/uploads/files/20240604/202406041717018a22e1161.png',
|
||||||
|
title: "线下收银订单金额",
|
||||||
|
value: 1000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'https://ceshi-engineering.lihaink.cn/uploads/files/20240604/202406041717013a08c6793.png',
|
||||||
|
title: "现金收银订单金额",
|
||||||
|
value: 1000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'https://ceshi-engineering.lihaink.cn/uploads/files/20240604/2024060417170103b0a9686.png',
|
||||||
|
title: "门店新增用户数",
|
||||||
|
value: 1000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'https://ceshi-engineering.lihaink.cn/uploads/files/20240604/20240604171701469b91377.png',
|
||||||
|
title: "门店成交用户数",
|
||||||
|
value: 1000
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: 'https://ceshi-engineering.lihaink.cn/uploads/files/20240604/20240604171701fbb680115.png',
|
||||||
|
title: "门店营业额",
|
||||||
|
value: 1000
|
||||||
|
},
|
||||||
|
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
const visitorOption = reactive({
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
data: [0],
|
data: []
|
||||||
axisLabel: {
|
|
||||||
rotate: 45,
|
|
||||||
color: '#333'
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
yAxis: [
|
yAxis: {
|
||||||
{
|
type: 'value'
|
||||||
type: 'value',
|
|
||||||
name: '数量',
|
|
||||||
position: 'left',
|
|
||||||
axisLabel: {
|
|
||||||
formatter: '{value}'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'value',
|
|
||||||
name: '金额',
|
|
||||||
position: 'right',
|
|
||||||
axisLabel: {
|
|
||||||
formatter: '{value}'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
grid: {
|
|
||||||
left: '3%',
|
|
||||||
right: '4%',
|
|
||||||
bottom: '3%',
|
|
||||||
containLabel: true
|
|
||||||
},
|
},
|
||||||
legend: {
|
legend: {
|
||||||
data: ['访问量']
|
data: ['营业额']
|
||||||
},
|
},
|
||||||
itemStyle: {
|
itemStyle: {
|
||||||
// 点的颜色。
|
// 点的颜色。
|
||||||
|
@ -147,7 +133,7 @@ const visitorOption: any = reactive({
|
||||||
},
|
},
|
||||||
series: [
|
series: [
|
||||||
{
|
{
|
||||||
name: '访问量',
|
name: '营业额',
|
||||||
data: [0],
|
data: [0],
|
||||||
type: 'line',
|
type: 'line',
|
||||||
smooth: true
|
smooth: true
|
||||||
|
@ -155,136 +141,88 @@ const visitorOption: any = reactive({
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
// 颜色
|
const tradTypeOption = reactive(
|
||||||
const colorList = ['#5DB1FF', '#4CD384', '#FFC46A', '#CAA5F1']
|
|
||||||
// 商品浏览量, 商品访客数, 加购件数, 下单件数, 支付件数, 支付金额, 成本金额, 退款金额, 退款件数, 访客-支付转化率
|
|
||||||
const basicList = reactive([
|
|
||||||
{
|
{
|
||||||
name: '商品浏览量',
|
title: {
|
||||||
type: 'browse',
|
text: '交易类型',
|
||||||
icon: 'RectangleCopy21',
|
left: 'center'
|
||||||
num: 0,
|
|
||||||
percent: 0
|
|
||||||
},
|
},
|
||||||
{
|
tooltip: {
|
||||||
name: '商品访客数',
|
trigger: 'item'
|
||||||
type: 'user',
|
|
||||||
icon: 'RectangleCopy5',
|
|
||||||
num: 0,
|
|
||||||
percent: 0
|
|
||||||
},
|
},
|
||||||
{
|
legend: {
|
||||||
name: '加购件数',
|
orient: 'vertical',
|
||||||
type: 'cart',
|
left: 'left'
|
||||||
icon: 'RectangleCopy13',
|
|
||||||
num: 0,
|
|
||||||
percent: 0
|
|
||||||
},
|
},
|
||||||
|
series: [
|
||||||
{
|
{
|
||||||
name: '下单件数',
|
type: 'pie',
|
||||||
type: 'order',
|
radius: '50%',
|
||||||
icon: 'RectangleCopy12',
|
data: [
|
||||||
num: 0,
|
{ value: 1048, name: '线上收银订单' },
|
||||||
percent: 0
|
{ value: 735, name: '现金收银订单' },
|
||||||
},
|
{ value: 580, name: '核销订单' },
|
||||||
{
|
{ value: 484, name: '充值订单' },
|
||||||
name: '支付件数',
|
],
|
||||||
type: 'pay',
|
emphasis: {
|
||||||
icon: 'RectangleCopy15',
|
itemStyle: {
|
||||||
num: 0,
|
shadowBlur: 10,
|
||||||
percent: 0
|
shadowOffsetX: 0,
|
||||||
},
|
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||||
{
|
|
||||||
name: '支付金额',
|
|
||||||
type: 'payPrice',
|
|
||||||
icon: 'RectangleCopy14',
|
|
||||||
num: 0,
|
|
||||||
percent: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '成本金额',
|
|
||||||
type: 'cost',
|
|
||||||
icon: 'RectangleCopy24',
|
|
||||||
num: 0,
|
|
||||||
percent: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '退款金额',
|
|
||||||
type: 'refundPrice',
|
|
||||||
icon: 'RectangleCopy32',
|
|
||||||
num: 0,
|
|
||||||
percent: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '退款件数',
|
|
||||||
type: 'refund',
|
|
||||||
icon: 'RectangleCopy19',
|
|
||||||
num: 0,
|
|
||||||
percent: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '访客-支付转化率',
|
|
||||||
type: 'payPercent',
|
|
||||||
icon: 'RectangleCopy4',
|
|
||||||
num: 0,
|
|
||||||
percent: 0
|
|
||||||
}
|
}
|
||||||
])
|
}
|
||||||
const startEndTime = ref(['', '']);
|
}
|
||||||
// 获取数据
|
]
|
||||||
const getData = () => {
|
}
|
||||||
let date = '';
|
)
|
||||||
if (startEndTime.value[0] && startEndTime.value[1]) date = moment(startEndTime.value[0]).format('YYYY/MM/DD') + '-' + moment(startEndTime.value[1]).format('YYYY/MM/DD');
|
|
||||||
|
|
||||||
|
|
||||||
|
const sendOption = reactive({
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis'
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
data: [820, 932, 901, 934, 1290, 1330, 1320],
|
||||||
|
type: 'line',
|
||||||
|
smooth: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
return
|
|
||||||
apiGetBasic({
|
|
||||||
date: date
|
|
||||||
}).then(res => {
|
|
||||||
basicList.forEach((item: any) => {
|
|
||||||
item.num = res[item.type].num;
|
|
||||||
item.percent = res[item.type].percent;
|
|
||||||
})
|
})
|
||||||
})
|
|
||||||
apiGetTrend({
|
|
||||||
date: date
|
const getData = () => {
|
||||||
}).then(res => {
|
getWorkbench()
|
||||||
|
.then((res: any) => {
|
||||||
|
|
||||||
// 清空echarts 数据
|
// 清空echarts 数据
|
||||||
visitorOption.xAxis.data = []
|
visitorOption.xAxis.data = []
|
||||||
visitorOption.series = []
|
visitorOption.series[0].data = []
|
||||||
|
|
||||||
visitorOption.legend.data = res.series.map((item: any) => item.name);
|
|
||||||
|
|
||||||
// 写入从后台拿来的数据
|
// 写入从后台拿来的数据
|
||||||
res.xAxis.forEach((item: any) => {
|
res.visitor.date.reverse().forEach((item: any) => {
|
||||||
visitorOption.xAxis.data.push(item)
|
visitorOption.xAxis.data.push(item)
|
||||||
})
|
})
|
||||||
visitorOption.series = res.series.map((item: any) => {
|
res.visitor.list[0].data.forEach((item: any) => {
|
||||||
return {
|
visitorOption.series[0].data.push(item)
|
||||||
...item,
|
|
||||||
yAxis: item.type == 'line' ? 0 : 1
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
})
|
||||||
|
.catch((err: any) => {
|
||||||
const sotreList = ref([]);
|
console.log('err', err)
|
||||||
const getList = () => {
|
|
||||||
let date = '';
|
|
||||||
if (startEndTime.value[0] && startEndTime.value[1]) date = moment(startEndTime.value[0]).format('YYYY/MM/DD') + '-' + moment(startEndTime.value[1]).format('YYYY/MM/DD');
|
|
||||||
|
|
||||||
return
|
|
||||||
apiGetProductRanking({
|
|
||||||
date: date
|
|
||||||
}).then(res => {
|
|
||||||
sotreList.value = res;
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getData()
|
getData()
|
||||||
getList()
|
|
||||||
})
|
})
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
</script>
|
|
@ -1,228 +0,0 @@
|
||||||
<template>
|
|
||||||
<el-card>
|
|
||||||
<el-form class="mb-[-16px]" :model="queryParams" label-width="80px">
|
|
||||||
<el-col :span="6">
|
|
||||||
<el-form-item label="时间筛选">
|
|
||||||
<el-date-picker v-model="date" type="daterange" range-separator="-" start-placeholder="开始时间"
|
|
||||||
end-placeholder="结束时间" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-form>
|
|
||||||
</el-card>
|
|
||||||
<el-card>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="6" class='flex mb-7' v-for="(item, index) in statisticLists" :key="index">
|
|
||||||
<img class="w-[50px] h-[50px] mr-2" :src="item.src" />
|
|
||||||
<el-statistic :title="item.title" :value="item.value" />
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-card>
|
|
||||||
<el-card>
|
|
||||||
<template #header>
|
|
||||||
营业趋势
|
|
||||||
</template>
|
|
||||||
<v-charts style="height: 350px" :option="visitorOption" :autoresize="true" />
|
|
||||||
</el-card>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="14">
|
|
||||||
<el-card class="h-[100%]">
|
|
||||||
<template #header>
|
|
||||||
交易数据
|
|
||||||
</template>
|
|
||||||
<tradData></tradData>
|
|
||||||
</el-card>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="10">
|
|
||||||
<el-card>
|
|
||||||
<template #header>
|
|
||||||
交易类型
|
|
||||||
</template>
|
|
||||||
<v-charts style="height: 350px" :option="tradTypeOption" :autoresize="true" />
|
|
||||||
</el-card>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-card>
|
|
||||||
<template #header>
|
|
||||||
配送订单统计
|
|
||||||
</template>
|
|
||||||
<v-charts style="height: 350px" :option="sendOption" :autoresize="true" />
|
|
||||||
</el-card>
|
|
||||||
|
|
||||||
<el-card>
|
|
||||||
<template #header>
|
|
||||||
配送订单统计
|
|
||||||
</template>
|
|
||||||
<sendData></sendData>
|
|
||||||
</el-card>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup name="manageProjectLists">
|
|
||||||
import { ref, reactive } from "vue"
|
|
||||||
import { getWorkbench } from '@/api/app'
|
|
||||||
import vCharts from 'vue-echarts'
|
|
||||||
import tradData from "./components/tradData.vue"
|
|
||||||
import sendData from "./components/sendData.vue"
|
|
||||||
|
|
||||||
const src = ref('https://cube.elemecdn.com/6/94/4d3ea53c084bad6931a56d5158a48jpeg.jpeg')
|
|
||||||
const date = ref("")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const statisticLists = reactive([
|
|
||||||
{
|
|
||||||
src: 'https://ceshi-engineering.lihaink.cn/uploads/files/20240604/20240604171701552002039.png',
|
|
||||||
title: "核销订单金额",
|
|
||||||
value: 1000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: "https://ceshi-engineering.lihaink.cn/uploads/files/20240604/2024060417170150a511510.png",
|
|
||||||
title: "余额消费金额",
|
|
||||||
value: 1000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'https://ceshi-engineering.lihaink.cn/uploads/files/20240604/20240604171701594ff8897.png',
|
|
||||||
title: "门店收益金额",
|
|
||||||
value: 1000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'https://ceshi-engineering.lihaink.cn/uploads/files/20240604/202406041717018a22e1161.png',
|
|
||||||
title: "线下收银订单金额",
|
|
||||||
value: 1000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'https://ceshi-engineering.lihaink.cn/uploads/files/20240604/202406041717013a08c6793.png',
|
|
||||||
title: "现金收银订单金额",
|
|
||||||
value: 1000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'https://ceshi-engineering.lihaink.cn/uploads/files/20240604/2024060417170103b0a9686.png',
|
|
||||||
title: "门店新增用户数",
|
|
||||||
value: 1000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'https://ceshi-engineering.lihaink.cn/uploads/files/20240604/20240604171701469b91377.png',
|
|
||||||
title: "门店成交用户数",
|
|
||||||
value: 1000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
src: 'https://ceshi-engineering.lihaink.cn/uploads/files/20240604/20240604171701fbb680115.png',
|
|
||||||
title: "门店营业额",
|
|
||||||
value: 1000
|
|
||||||
},
|
|
||||||
|
|
||||||
])
|
|
||||||
|
|
||||||
|
|
||||||
const visitorOption = reactive({
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
data: []
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value'
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
data: ['营业额']
|
|
||||||
},
|
|
||||||
itemStyle: {
|
|
||||||
// 点的颜色。
|
|
||||||
color: 'red'
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis'
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '营业额',
|
|
||||||
data: [0],
|
|
||||||
type: 'line',
|
|
||||||
smooth: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
|
|
||||||
const tradTypeOption = reactive(
|
|
||||||
{
|
|
||||||
title: {
|
|
||||||
text: '交易类型',
|
|
||||||
left: 'center'
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'item'
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
orient: 'vertical',
|
|
||||||
left: 'left'
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: 'pie',
|
|
||||||
radius: '50%',
|
|
||||||
data: [
|
|
||||||
{ value: 1048, name: '线上收银订单' },
|
|
||||||
{ value: 735, name: '现金收银订单' },
|
|
||||||
{ value: 580, name: '核销订单' },
|
|
||||||
{ value: 484, name: '充值订单' },
|
|
||||||
],
|
|
||||||
emphasis: {
|
|
||||||
itemStyle: {
|
|
||||||
shadowBlur: 10,
|
|
||||||
shadowOffsetX: 0,
|
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const sendOption = reactive({
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis'
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value'
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
data: [820, 932, 901, 934, 1290, 1330, 1320],
|
|
||||||
type: 'line',
|
|
||||||
smooth: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const getData = () => {
|
|
||||||
getWorkbench()
|
|
||||||
.then((res: any) => {
|
|
||||||
|
|
||||||
// 清空echarts 数据
|
|
||||||
visitorOption.xAxis.data = []
|
|
||||||
visitorOption.series[0].data = []
|
|
||||||
|
|
||||||
// 写入从后台拿来的数据
|
|
||||||
res.visitor.date.reverse().forEach((item: any) => {
|
|
||||||
visitorOption.xAxis.data.push(item)
|
|
||||||
})
|
|
||||||
res.visitor.list[0].data.forEach((item: any) => {
|
|
||||||
visitorOption.series[0].data.push(item)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.catch((err: any) => {
|
|
||||||
console.log('err', err)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getData()
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
|
|
@ -0,0 +1,290 @@
|
||||||
|
<template>
|
||||||
|
<div class="workbench">
|
||||||
|
<el-card shadow="never" class=" !border-none">
|
||||||
|
<div class="mb-6 flex justify-between items-center">
|
||||||
|
<span class="text-2xl">商品概况</span>
|
||||||
|
<div class="flex items-center text-sm">
|
||||||
|
<span class="mr-4">时间筛选: </span>
|
||||||
|
<el-date-picker v-model="startEndTime" type="daterange" range-separator="至" start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期" unlink-panels :shortcuts="shortcuts" />
|
||||||
|
<el-button type="primary" class="ml-4" @click="getData">查询</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-wrap">
|
||||||
|
<div class="w-1/5 flex mb-6" v-for="(item, index) in basicList" :key="index">
|
||||||
|
<div class="mr-2">
|
||||||
|
<div class="rounded-full p-2" :style="{ 'background-color': colorList[index % 4] }">
|
||||||
|
<iconfont :iconName="item.icon" white className="text-6xl" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="text-info">{{ item.name }}</div>
|
||||||
|
<div class="text-6xl">{{ item.num }}</div>
|
||||||
|
<div class="text-info">环比增长: <span :class="item.percent > 0 ? 'text-success' : 'text-danger'">{{
|
||||||
|
item.percent }}%</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<v-charts style="height: 400px" :option="visitorOption" :autoresize="true" />
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
<el-card shadow="never" class="mt-4 !border-none">
|
||||||
|
<div class="mb-6 flex justify-between items-center">
|
||||||
|
<span class="text-2xl">商品排行</span>
|
||||||
|
<div class="flex items-center text-sm">
|
||||||
|
<span class="mr-4">时间筛选: </span>
|
||||||
|
<el-date-picker v-model="startEndTime" type="daterange" range-separator="至" start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期" unlink-panels :shortcuts="shortcuts" />
|
||||||
|
<el-button type="primary" class="ml-4" @click="getData">查询</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-table :data="sotreList">
|
||||||
|
<el-table-column label="商品图片">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-image :src="row.image" fit="cover" style="width: 50px; height: 50px" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="商品名称" prop="store_name" min-width="250" />
|
||||||
|
<el-table-column label="游览量" prop="visit" min-width="120" />
|
||||||
|
<el-table-column label="访客数" prop="user" min-width="120" />
|
||||||
|
<el-table-column label="加购件数" prop="cart" min-width="120" />
|
||||||
|
<el-table-column label="下单件数" prop="orders" min-width="120" />
|
||||||
|
<el-table-column label="支付件数" prop="pay" min-width="120" />
|
||||||
|
<el-table-column label="支付金额" prop="price" min-width="120" />
|
||||||
|
<el-table-column label="收藏数" prop="collect" min-width="120" />
|
||||||
|
<el-table-column label="毛利率(%)" prop="profit" min-width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<span>{{ row.profit }}%</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup name="product">
|
||||||
|
// import { apiGetBasic, apiGetTrend, apiGetProductRanking } from '@/api/workbench'
|
||||||
|
import moment from 'moment'
|
||||||
|
import vCharts from 'vue-echarts'
|
||||||
|
|
||||||
|
const shortcuts = [
|
||||||
|
{
|
||||||
|
text: '近一周',
|
||||||
|
value: () => {
|
||||||
|
const end = new Date()
|
||||||
|
const start = new Date()
|
||||||
|
start.setDate(start.getDate() - 7)
|
||||||
|
return [start, end]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '近一月',
|
||||||
|
value: () => {
|
||||||
|
const end = new Date()
|
||||||
|
const start = new Date()
|
||||||
|
start.setMonth(start.getMonth() - 1)
|
||||||
|
return [start, end]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '近三月',
|
||||||
|
value: () => {
|
||||||
|
const end = new Date()
|
||||||
|
const start = new Date()
|
||||||
|
start.setMonth(start.getMonth() - 3)
|
||||||
|
return [start, end]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
// 表单数据
|
||||||
|
const visitorOption: any = reactive({
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: [0],
|
||||||
|
axisLabel: {
|
||||||
|
rotate: 45,
|
||||||
|
color: '#333'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
name: '数量',
|
||||||
|
position: 'left',
|
||||||
|
axisLabel: {
|
||||||
|
formatter: '{value}'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
name: '金额',
|
||||||
|
position: 'right',
|
||||||
|
axisLabel: {
|
||||||
|
formatter: '{value}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['访问量']
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
// 点的颜色。
|
||||||
|
color: 'red'
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '访问量',
|
||||||
|
data: [0],
|
||||||
|
type: 'line',
|
||||||
|
smooth: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
// 颜色
|
||||||
|
const colorList = ['#5DB1FF', '#4CD384', '#FFC46A', '#CAA5F1']
|
||||||
|
// 商品浏览量, 商品访客数, 加购件数, 下单件数, 支付件数, 支付金额, 成本金额, 退款金额, 退款件数, 访客-支付转化率
|
||||||
|
const basicList = reactive([
|
||||||
|
{
|
||||||
|
name: '商品浏览量',
|
||||||
|
type: 'browse',
|
||||||
|
icon: 'RectangleCopy21',
|
||||||
|
num: 0,
|
||||||
|
percent: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '商品访客数',
|
||||||
|
type: 'user',
|
||||||
|
icon: 'RectangleCopy5',
|
||||||
|
num: 0,
|
||||||
|
percent: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '加购件数',
|
||||||
|
type: 'cart',
|
||||||
|
icon: 'RectangleCopy13',
|
||||||
|
num: 0,
|
||||||
|
percent: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '下单件数',
|
||||||
|
type: 'order',
|
||||||
|
icon: 'RectangleCopy12',
|
||||||
|
num: 0,
|
||||||
|
percent: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '支付件数',
|
||||||
|
type: 'pay',
|
||||||
|
icon: 'RectangleCopy15',
|
||||||
|
num: 0,
|
||||||
|
percent: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '支付金额',
|
||||||
|
type: 'payPrice',
|
||||||
|
icon: 'RectangleCopy14',
|
||||||
|
num: 0,
|
||||||
|
percent: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '成本金额',
|
||||||
|
type: 'cost',
|
||||||
|
icon: 'RectangleCopy24',
|
||||||
|
num: 0,
|
||||||
|
percent: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '退款金额',
|
||||||
|
type: 'refundPrice',
|
||||||
|
icon: 'RectangleCopy32',
|
||||||
|
num: 0,
|
||||||
|
percent: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '退款件数',
|
||||||
|
type: 'refund',
|
||||||
|
icon: 'RectangleCopy19',
|
||||||
|
num: 0,
|
||||||
|
percent: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '访客-支付转化率',
|
||||||
|
type: 'payPercent',
|
||||||
|
icon: 'RectangleCopy4',
|
||||||
|
num: 0,
|
||||||
|
percent: 0
|
||||||
|
}
|
||||||
|
])
|
||||||
|
const startEndTime = ref(['', '']);
|
||||||
|
// 获取数据
|
||||||
|
const getData = () => {
|
||||||
|
let date = '';
|
||||||
|
if (startEndTime.value[0] && startEndTime.value[1]) date = moment(startEndTime.value[0]).format('YYYY/MM/DD') + '-' + moment(startEndTime.value[1]).format('YYYY/MM/DD');
|
||||||
|
|
||||||
|
return
|
||||||
|
apiGetBasic({
|
||||||
|
date: date
|
||||||
|
}).then(res => {
|
||||||
|
basicList.forEach((item: any) => {
|
||||||
|
item.num = res[item.type].num;
|
||||||
|
item.percent = res[item.type].percent;
|
||||||
|
})
|
||||||
|
})
|
||||||
|
apiGetTrend({
|
||||||
|
date: date
|
||||||
|
}).then(res => {
|
||||||
|
// 清空echarts 数据
|
||||||
|
visitorOption.xAxis.data = []
|
||||||
|
visitorOption.series = []
|
||||||
|
|
||||||
|
visitorOption.legend.data = res.series.map((item: any) => item.name);
|
||||||
|
|
||||||
|
// 写入从后台拿来的数据
|
||||||
|
res.xAxis.forEach((item: any) => {
|
||||||
|
visitorOption.xAxis.data.push(item)
|
||||||
|
})
|
||||||
|
visitorOption.series = res.series.map((item: any) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
yAxis: item.type == 'line' ? 0 : 1
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const sotreList = ref([]);
|
||||||
|
const getList = () => {
|
||||||
|
let date = '';
|
||||||
|
if (startEndTime.value[0] && startEndTime.value[1]) date = moment(startEndTime.value[0]).format('YYYY/MM/DD') + '-' + moment(startEndTime.value[1]).format('YYYY/MM/DD');
|
||||||
|
|
||||||
|
return
|
||||||
|
apiGetProductRanking({
|
||||||
|
date: date
|
||||||
|
}).then(res => {
|
||||||
|
sotreList.value = res;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getData()
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
Loading…
Reference in New Issue