提交 6269e420 authored 作者: lidongxu's avatar lidongxu

Merge branch 'dev'

......@@ -24,7 +24,4 @@ VITE_APP_REPORT_SHARE_PREVIEW_URL = '#/report'
VITE_APP_REPORT_EDIT_URL = '#/report/jmreport/index'
# 促销计划上报模板表格
VITE_APP_PLAN_TEMPLATE_EXCEL = 'https://link-promotion.oss-cn-shanghai.aliyuncs.com/file/%E6%96%B0%E5%A2%9E%E6%88%96%E4%BF%AE%E6%94%B9%E8%AE%A1%E5%88%92-%E6%A8%A1%E6%9D%BF4.0.xlsx'
# 腾讯地图接口地址
VITE_APP_TENCENT_MAP_API = '/tencent_map_api'
\ No newline at end of file
VITE_APP_PLAN_TEMPLATE_EXCEL = 'https://link-promotion.oss-cn-shanghai.aliyuncs.com/file/%E6%96%B0%E5%A2%9E%E6%88%96%E4%BF%AE%E6%94%B9%E8%AE%A1%E5%88%92-%E6%A8%A1%E6%9D%BF4.0.xlsx'
\ No newline at end of file
......@@ -23,7 +23,4 @@ VITE_APP_REPORT_SHARE_PREVIEW_URL = '#/report'
VITE_APP_REPORT_EDIT_URL = '#/report/jmreport/index'
# 促销计划上报模板表格
VITE_APP_PLAN_TEMPLATE_EXCEL = 'https://link-promotion.oss-cn-shanghai.aliyuncs.com/file/%E6%96%B0%E5%A2%9E%E6%88%96%E4%BF%AE%E6%94%B9%E8%AE%A1%E5%88%92-%E6%A8%A1%E6%9D%BF4.0.xlsx'
# 腾讯地图接口地址
VITE_APP_TENCENT_MAP_API = 'https://apis.map.qq.com/ws/geocoder/v1'
\ No newline at end of file
VITE_APP_PLAN_TEMPLATE_EXCEL = 'https://link-promotion.oss-cn-shanghai.aliyuncs.com/file/%E6%96%B0%E5%A2%9E%E6%88%96%E4%BF%AE%E6%94%B9%E8%AE%A1%E5%88%92-%E6%A8%A1%E6%9D%BF4.0.xlsx'
\ No newline at end of file
......@@ -22,7 +22,4 @@ VITE_APP_REPORT_SHARE_PREVIEW_URL = '#/report'
VITE_APP_REPORT_EDIT_URL = '#/report/jmreport/index'
# 促销计划上报模板表格
VITE_APP_PLAN_TEMPLATE_EXCEL = 'https://link-promotion.oss-cn-shanghai.aliyuncs.com/file/%E6%96%B0%E5%A2%9E%E6%88%96%E4%BF%AE%E6%94%B9%E8%AE%A1%E5%88%92-%E6%A8%A1%E6%9D%BF4.0.xlsx'
# 腾讯地图接口地址
VITE_APP_TENCENT_MAP_API = 'https://apis.map.qq.com/ws/geocoder/v1'
\ No newline at end of file
VITE_APP_PLAN_TEMPLATE_EXCEL = 'https://link-promotion.oss-cn-shanghai.aliyuncs.com/file/%E6%96%B0%E5%A2%9E%E6%88%96%E4%BF%AE%E6%94%B9%E8%AE%A1%E5%88%92-%E6%A8%A1%E6%9D%BF4.0.xlsx'
\ No newline at end of file
......@@ -8,7 +8,7 @@
<meta name="renderer"
content="webkit">
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="icon"
href="/favicon.ico">
<title>
......
......@@ -2,11 +2,9 @@ import request from '@/utils/request'
// 逆地址编码
export const getLocation = (params) => {
return request({
baseURL: import.meta.env.VITE_APP_TENCENT_MAP_API,
url: '/',
url: '/system/tencent/lbs/address',
params: {
location: params.lat + ',' + params.lng, // GCJ02坐标系(经度,维度)
key: 'UTEBZ-UJ3KG-OORQO-QT3PT-JDWU7-YRBZA'
location: params.lat + ',' + params.lng // GCJ02坐标系(经度,维度)
}
})
}
\ No newline at end of file
......@@ -33,3 +33,20 @@ export function createInspectionTaskDetailAPI(data) {
data
})
}
// 售点稽查-任务列表
export function getInspectionTaskListAPI(params) {
return request({
url: '/operation/risk/query/i_store/page',
params
})
}
// 售点稽查-删除 tab 里面子任务中的小分组
export function deleteInspectionTaskAPI(params) {
return request({
url: '/operation/risk/core/d_store_detail',
method: 'DELETE',
params
})
}
\ No newline at end of file
/**
* v-hasRole 角色权限处理
* Copyright (c) 2019 ruoyi
*/
/**
* v-hasRole 角色权限处理
* Copyright (c) 2019 ruoyi
*/
import useUserStore from '@/store/modules/user'
export default {
......@@ -10,10 +10,8 @@ export default {
const { value } = binding
const super_admin = "admin";
const roles = useUserStore().roles
if (value && value instanceof Array && value.length > 0) {
const roleFlag = value
const hasRole = roles.some(role => {
return super_admin === role || roleFlag.includes(role)
})
......
import Cookies from 'js-cookie'
import { set } from 'nprogress';
const useAppStore = defineStore(
'app',
......@@ -12,7 +11,7 @@ const useAppStore = defineStore(
},
device: 'desktop',
size: Cookies.get('size') || 'default',
belongSys: Cookies.get('belongSys') || '链路中心',
belongSys: Cookies.get('belongSys') || 0,
}),
actions: {
toggleSideBar(withoutAnimation) {
......@@ -28,6 +27,7 @@ const useAppStore = defineStore(
}
},
closeSideBar({ withoutAnimation }) {
// 屏幕宽度小于 992px,或者在移动端,默认侧边栏导航是关闭的
Cookies.set('sidebarStatus', 0)
this.sidebar.opened = false
this.sidebar.withoutAnimation = withoutAnimation
......
......@@ -44,7 +44,16 @@ const usePermissionStore = defineStore(
// 链路中心
res.data = res.data.filter(item => item.belongSys == 0)
} else {
// 勤策
// 勤策移动端
const result = res.data.filter(item => item.belongSys == 1)
if (result.length == 0) {
showNotify({
message: '您没有《勤策移动端》菜单,联系"李秋林"开通!',
type: 'danger',
duration: 5000
})
return
}
res.data = res.data.filter(item => item.belongSys == 1)[0].children
}
const sdata = JSON.parse(JSON.stringify(res.data))
......
......@@ -109,7 +109,7 @@ export default defineStore(
},
getters: {
/**
* 获取促销系统身份 (0 null 为职能角色,1 为城市经理)
* 获取促销系统身份 (null 2 为职能角色,1 为城市经理)
* @param {*} state
* @returns (true 城市经理)(false 职能角色)
*/
......
......@@ -2,15 +2,14 @@
<div class="mobile-page-container">
<!-- 类型选择 -->
<div class="category-select">
<van-field label-width="4rem"
<van-field label-width="3.8rem"
label-position="left"
label="品类选择:"
:model-value="selectedTypeObj.label"
placeholder="请输入">
<template #input>
<el-select v-model="selectedTypeObj"
placeholder="请选择"
filterable>
placeholder="请选择">
<el-option v-for="item in typeOptions"
:label="item.label"
:value="item" />
......@@ -20,10 +19,11 @@
<van-field v-model="selectedTypeObj.price"
type="number"
:label="selectedTypeObj.label + ' 价格:'"
label-width="4rem"
label-width="3.8rem"
placeholder="请输入价格"
clearable
class="search-input" />
class="search-input"
@change="handlePriceChange" />
</div>
<!-- 品类信息 -->
<div class="table-container">
......@@ -47,7 +47,10 @@
<template #input>
<el-date-picker v-model="obj.value"
type="month"
placeholder="选择月份" />
:editable="false"
value-format="YYYY-MM"
placeholder="选择月份"
@change="handleTasteChange(index)" />
</template>
</van-field>
</div>
......@@ -58,13 +61,62 @@
</template>
<script setup>
import { createInspectionTaskDetailAPI } from '@/api'
const props = defineProps({
form: {
type: Object,
default: () => { }
}
})
const nowRstdId = ref('') // 当前品类任务部分 ID
// 品类型
// 后台用的英文字段,和我们的 label 名字做映射
const typeMap = {
' 虎皮凤爪 210g': {
priceKey: 'priceHp210',
tasteDateKey: 'kwYmHp210Map'
},
' 虎皮凤爪 105g': {
priceKey: 'priceHp105',
tasteDateKey: 'kwYmHp105Map'
},
' 虎皮凤爪 68g': {
priceKey: 'priceHp68',
tasteDateKey: 'kwYmHp68Map'
},
' 鸡肉豆堡 120g': {
priceKey: 'priceJrdb120',
tasteDateKey: 'kwYmJrdb120Map'
},
' 牛肉豆堡 120g': {
priceKey: 'priceNrdb120',
tasteDateKey: 'kwYmNrdb120Map'
},
' 去骨凤爪 72g': {
priceKey: 'priceQg72',
tasteDateKey: 'kwYmQg72Map'
},
' 去骨凤爪 138g': {
priceKey: 'priceQg138',
tasteDateKey: 'kwYmQg138Map'
},
' 虎皮小鸡腿 80g': {
priceKey: 'priceHpjt80',
tasteDateKey: 'kwYmHpjt80Map'
},
' 老卤系列 ': {
priceKey: 'priceLl',
tasteDateKey: 'kwYmLlMap'
},
' 单支虎皮凤爪 ': {
priceKey: 'priceHpDz',
tasteDateKey: 'kwYmHpDzMap'
},
' 散称虎皮凤爪 ': {
priceKey: 'priceHpSc',
tasteDateKey: 'kwYmHpScMap'
},
}
const typeOptions = ref([
{
label: ' 虎皮凤爪 210g', value: ' 虎皮凤爪 210g', price: '', taste: [
......@@ -257,28 +309,66 @@ const typeOptions = ref([
]);
const selectedTypeObj = ref(typeOptions.value[0])
// 创建任务
const createTask = () => {
displayGroup.value.push({
type: selectedTypeObj.value.value,
taste: selectedTypeObj.value.taste.map(item => ({
name: item.name,
value: ''
}))
// 价格改变
const handlePriceChange = async () => {
const prop = typeMap[selectedTypeObj.value.label].priceKey
const res = await createInspectionTaskDetailAPI({
taskDetail: {
rstId: props.form.rstId,
rstdId: nowRstdId.value,
detailName: '品类信息',
[prop]: selectedTypeObj.value.price * 1
}
})
showNotify({ type: 'success', message: '价格,保存成功' })
}
// 口味生产日期设置
const handleTasteChange = async (index) => {
console.log(selectedTypeObj.value)
const prop = typeMap[selectedTypeObj.value.label].tasteDateKey
await createInspectionTaskDetailAPI({
taskDetail: {
rstId: props.form.rstId,
rstdId: nowRstdId.value,
detailName: '品类信息',
[prop]: selectedTypeObj.value.taste.reduce((acc, item) => {
acc[item.name] = item.value;
return acc;
}, {})
}
})
}
const init = () => {
if (props.form.detailMap) {
if (props.form.detailMap['品类信息']) {
checkProperty(props.form.detailMap['品类信息'])
displayGroup.value = props.form.detailMap['品类信息'] || []
// 回显
nowRstdId.value = props.form.detailMap['品类信息'][0].rstdId // 详情ID
// 循环设置
typeOptions.value.forEach(item => {
const priceProp = typeMap[item.label].priceKey // 设置价格
item.price = props.form.detailMap['品类信息'][0][priceProp]
const tasteProp = typeMap[item.label].tasteDateKey // 设置口味日期
const targetTasteObj = props.form.detailMap['品类信息'][0][tasteProp]
if (targetTasteObj) {
item.taste.forEach(item => {
item.value = targetTasteObj[item.name] // 取出日期
})
}
})
return
}
}
// 没传递则自己至少新建 1 个
if (displayGroup.value.length === 0) {
createTask()
}
// 手动创建品类信息,得到 rstdId
createInspectionTaskDetailAPI({
taskDetail: {
rstId: props.form.rstId,
detailName: '品类信息'
}
}).then(res => {
nowRstdId.value = res.data.rstdId
})
}
defineExpose({
init
......@@ -288,7 +378,7 @@ defineExpose({
<style lang="scss"
scoped>
.mobile-page-container {
padding: 10px;
padding: .2667rem;
background-color: #fff;
// 类型选择
......@@ -298,35 +388,39 @@ defineExpose({
.van-cell {
padding: 0;
align-items: center;
// font-size: 14px;
// font-size: .3733rem;
// font-weight: 900;
.el-select {
width: 150px;
width: 4rem;
}
}
.search-input {
margin-top: 10px;
margin-top: .2667rem;
::v-deep(input) {
border-bottom: 1px solid gray;
}
}
}
// 表格容器
.table-container {
margin-top: 10px;
margin-top: .2667rem;
}
.custom-table {
width: 100%;
border: 1px solid #ccc;
border: .0267rem solid #ccc;
border-collapse: collapse; // 模拟表格边框合并
.table-row {
display: flex;
width: 100%;
height: 44px;
height: 1.1733rem;
&.header-row {
background-color: #e5e5e5;
......@@ -349,9 +443,9 @@ defineExpose({
display: flex;
align-items: center;
justify-content: center;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
font-size: 14px;
border-right: .0267rem solid #ccc;
border-bottom: .0267rem solid #ccc;
font-size: .3733rem;
color: #333;
&:last-child {
......@@ -359,14 +453,14 @@ defineExpose({
}
&.first-column {
width: 120px;
width: 3.2rem;
font-weight: 500;
}
&.second-column {
background: white;
flex: 1;
padding: 0 8px;
padding: 0 .2133rem;
}
}
......@@ -375,7 +469,7 @@ defineExpose({
width: 100%;
height: 100%;
text-align: center;
font-size: 14px;
font-size: .3733rem;
padding: 0;
::v-deep(.van-cell__value) {
......
......@@ -3,7 +3,12 @@
<!-- 常规陈列 -->
<div class="item"
v-for="(obj, index) in displayGroup">
<p class="title">常规陈列{{ index + 1 }}</p>
<p class="title">
<span>常规陈列{{ index + 1 }}</span>
<van-icon name="delete"
size="0.45rem"
@click="deleteItem(obj, index)" />
</p>
<van-cell-group inset>
<van-field v-model="obj.modal"
name="modal"
......@@ -30,7 +35,7 @@
:model-value="obj.photoArr"
:name="index"
:after-read="displayPhotosRead"
preview-size="78"
preview-size="2.13333rem"
@delete="deletedisplayPhotos">
</van-uploader>
</template>
......@@ -54,7 +59,7 @@
<!-- 新增按钮 -->
<van-button class="add-item"
type="primary"
@click="createTask">新增一组陈列</van-button>
@click="createTask">新增一组</van-button>
<!-- 总体判定 -->
<div class="overall">
<p class="title">常规陈列总体判定结果:</p>
......@@ -72,7 +77,7 @@
</template>
<script setup>
import { uploadFileToOSSAPI, createInspectionTaskAPI, createInspectionTaskDetailAPI } from '@/api'
import { uploadFileToOSSAPI, createInspectionTaskAPI, createInspectionTaskDetailAPI, deleteInspectionTaskAPI } from '@/api'
import useUserStore from '@/store/modules/user'
import { v4 as uuidv4 } from 'uuid'
......@@ -126,6 +131,30 @@ const init = () => {
createTask()
}
}
// 删除分组
const isDeleteNow = ref(false)
const deleteItem = async (obj, index) => {
// 确认询问框
showConfirmDialog({
title: '删除提示',
message: '确定删除吗?',
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
isDeleteNow.value = true
await deleteInspectionTaskAPI({
rstdId: obj.rstdId
})
displayGroup.value.splice(index, 1)
nextTick(() => {
isDeleteNow.value = false
})
showNotify({ type: 'success', message: '删除成功' })
})
}
/*************** 基本信息 ***************/
// 形式修改
const handleModalityChange = async (index) => {
......@@ -154,9 +183,11 @@ const handleCostChange = async (index) => {
const displayPhotosRead = async (file, { name, index }) => {
// name:是当前照片组件所在陈列组的索引
// index: 当前照片组的索引
const date = new Date()
const month = date.getMonth() + 1
const theDate = date.getDate()
const target = displayGroup.value[name]
const pictureUrl = await uploadFileToOSSAPI(`risk/displayPhoto/${useUserStore().empInfo.empNo}/${props.form.storeCode}/${uuidv4()}.png`, file.file)
const pictureUrl = await uploadFileToOSSAPI(`risk/${date.getFullYear()}-${month}/displayPhoto/${useUserStore().empInfo.empNo}/${props.form.storeCode}/${uuidv4()}.png`, file.file)
target.photoArr.push({
url: pictureUrl
})
......@@ -186,6 +217,7 @@ const deletedisplayPhotos = async (file, { name, index }) => {
}
// 核查结果
const handleVerifyChange = async (index) => {
if (isDeleteNow.value) return
const target = displayGroup.value[index]
await createInspectionTaskDetailAPI({
taskDetail: {
......@@ -224,6 +256,9 @@ defineExpose({
margin: 0;
font-weight: 900;
color: var(--main-color);
display: flex;
justify-content: space-between;
}
/* 每个分组 */
......
......@@ -3,7 +3,12 @@
<!-- 档期补差 -->
<div class="item"
v-for="(obj, index) in displayGroup">
<p class="title">档期补差{{ index + 1 }}</p>
<p class="title">
<span>档期补差{{ index + 1 }}</span>
<van-icon name="delete"
size="0.45rem"
@click="deleteItem(obj, index)" />
</p>
<van-cell-group inset>
<van-field v-model="obj.modal"
name="modal"
......@@ -29,7 +34,7 @@
:model-value="obj.photoArr"
:name="index"
:after-read="displayPhotosRead"
preview-size="78"
preview-size="2.13333rem"
@delete="deletedisplayPhotos">
</van-uploader>
</template>
......@@ -53,7 +58,7 @@
<!-- 新增按钮 -->
<van-button class="add-item"
type="primary"
@click="createTask">新增一组陈列</van-button>
@click="createTask">新增一组</van-button>
<!-- 总体判定 -->
<!-- <div class="overall">
<p class="title">档期陈列总体判定结果:</p>
......@@ -71,7 +76,7 @@
<script setup>
import { uploadFileToOSSAPI, createInspectionTaskAPI, createInspectionTaskDetailAPI } from '@/api'
import { uploadFileToOSSAPI, createInspectionTaskAPI, createInspectionTaskDetailAPI, deleteInspectionTaskAPI } from '@/api'
import useUserStore from '@/store/modules/user'
import { v4 as uuidv4 } from 'uuid'
......@@ -125,6 +130,29 @@ const init = () => {
createTask()
}
}
// 删除分组
const isDeleteNow = ref(false)
const deleteItem = async (obj, index) => {
// 确认询问框
showConfirmDialog({
title: '删除提示',
message: '确定删除吗?',
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
isDeleteNow.value = true
await deleteInspectionTaskAPI({
rstdId: obj.rstdId
})
displayGroup.value.splice(index, 1)
nextTick(() => {
isDeleteNow.value = false
})
showNotify({ type: 'success', message: '删除成功' })
})
}
/*************** 基本信息 ***************/
// 形式修改
const handleModalityChange = async (index) => {
......@@ -153,9 +181,11 @@ const handleCostChange = async (index) => {
const displayPhotosRead = async (file, { name, index }) => {
// name:是当前照片组件所在陈列组的索引
// index: 当前照片组的索引
const date = new Date()
const month = date.getMonth() + 1
const theDate = date.getDate()
const target = displayGroup.value[name]
const pictureUrl = await uploadFileToOSSAPI(`risk/scheduleAdjustmentPhoto/${useUserStore().empInfo.empNo}/${props.form.storeCode}/${uuidv4()}.png`, file.file)
const pictureUrl = await uploadFileToOSSAPI(`risk/${date.getFullYear()}-${month}/scheduleAdjustmentPhoto/${useUserStore().empInfo.empNo}/${props.form.storeCode}/${uuidv4()}.png`, file.file)
target.photoArr.push({
url: pictureUrl
})
......@@ -185,6 +215,7 @@ const deletedisplayPhotos = async (file, { name, index }) => {
}
// 核查结果
const handleVerifyChange = async (index) => {
if (isDeleteNow.value) return
const target = displayGroup.value[index]
await createInspectionTaskDetailAPI({
taskDetail: {
......@@ -213,6 +244,9 @@ defineExpose({
margin: 0;
font-weight: 900;
color: var(--main-color);
display: flex;
justify-content: space-between;
}
/* 每个分组 */
......
......@@ -3,7 +3,12 @@
<!-- 档期陈列 -->
<div class="item"
v-for="(obj, index) in displayGroup">
<p class="title">档期陈列{{ index + 1 }}</p>
<p class="title">
<span>档期陈列{{ index + 1 }}</span>
<van-icon name="delete"
size="0.45rem"
@click="deleteItem(obj, index)" />
</p>
<van-cell-group inset>
<van-field v-model="obj.modal"
name="modal"
......@@ -29,7 +34,7 @@
:model-value="obj.photoArr"
:name="index"
:after-read="displayPhotosRead"
preview-size="78"
preview-size="2.13333rem"
@delete="deletedisplayPhotos">
</van-uploader>
</template>
......@@ -53,11 +58,11 @@
<!-- 新增按钮 -->
<van-button class="add-item"
type="primary"
@click="createTask">新增一组陈列</van-button>
@click="createTask">新增一组</van-button>
<!-- 总体判定 -->
<div class="overall">
<p class="title">档期陈列总体判定结果:</p>
<van-checkbox-group v-model="form.cgclRiskRArr"
<van-checkbox-group v-model="form.dqclRiskRArr"
direction="horizontal"
shape="square"
@change="handleOverallChange">
......@@ -71,7 +76,7 @@
</template>
<script setup>
import { uploadFileToOSSAPI, createInspectionTaskAPI, createInspectionTaskDetailAPI } from '@/api'
import { uploadFileToOSSAPI, createInspectionTaskAPI, createInspectionTaskDetailAPI, deleteInspectionTaskAPI } from '@/api'
import useUserStore from '@/store/modules/user'
import { v4 as uuidv4 } from 'uuid'
......@@ -125,6 +130,29 @@ const init = () => {
createTask()
}
}
// 删除分组
const isDeleteNow = ref(false)
const deleteItem = async (obj, index) => {
// 确认询问框
showConfirmDialog({
title: '删除提示',
message: '确定删除吗?',
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
isDeleteNow.value = true
await deleteInspectionTaskAPI({
rstdId: obj.rstdId
})
displayGroup.value.splice(index, 1)
nextTick(() => {
isDeleteNow.value = false
})
showNotify({ type: 'success', message: '删除成功' })
})
}
/*************** 基本信息 ***************/
// 形式修改
const handleModalityChange = async (index) => {
......@@ -153,9 +181,11 @@ const handleCostChange = async (index) => {
const displayPhotosRead = async (file, { name, index }) => {
// name:是当前照片组件所在陈列组的索引
// index: 当前照片组的索引
const date = new Date()
const month = date.getMonth() + 1
const theDate = date.getDate()
const target = displayGroup.value[name]
const pictureUrl = await uploadFileToOSSAPI(`risk/scheduleDisplayPhoto/${useUserStore().empInfo.empNo}/${props.form.storeCode}/${uuidv4()}.png`, file.file)
const pictureUrl = await uploadFileToOSSAPI(`risk/${date.getFullYear()}-${month}/scheduleDisplayPhoto/${useUserStore().empInfo.empNo}/${props.form.storeCode}/${uuidv4()}.png`, file.file)
target.photoArr.push({
url: pictureUrl
})
......@@ -185,6 +215,7 @@ const deletedisplayPhotos = async (file, { name, index }) => {
}
// 核查结果
const handleVerifyChange = async (index) => {
if (isDeleteNow.value) return
const target = displayGroup.value[index]
await createInspectionTaskDetailAPI({
taskDetail: {
......@@ -201,7 +232,7 @@ const handleOverallChange = async () => {
if (props.isInitializing) return
await createInspectionTaskAPI({
rstId: props.form.rstId,
cgclRiskRArr: props.form.cgclRiskRArr
dqclRiskRArr: props.form.dqclRiskRArr
})
showNotify({ type: 'success', message: '核查结果,保存成功' })
}
......@@ -223,6 +254,9 @@ defineExpose({
margin: 0;
font-weight: 900;
color: var(--main-color);
display: flex;
justify-content: space-between;
}
/* 每个分组 */
......
......@@ -6,45 +6,63 @@
<div class="terminal-info-container">
<p class="title">录入终端信息</p>
<div class="content">
<!-- 终端名称输入 -->
<van-field v-model="terminalName"
label="终端名称:"
label-align="top"
placeholder="请输入"
class="input-field" />
<!-- 门头照上传 -->
<div class="header-photo-section">
<van-field label="门头照"
label-align="top">
<van-form ref="myFormRef">
<!-- 终端名称输入 -->
<van-field v-model="form.storeName"
label="终端名称:"
label-align="top"
placeholder="请输入"
class="input-field"
:rules="[{ required: true, message: '请输入终端名称' }]" />
<!-- 门头照上传 -->
<div class="header-photo-section">
<van-field label="门头照"
label-align="top"
:rules="[{ required: true, message: '请上传门头照' }]">
<template #input>
<van-uploader :max-count="1"
accept="image/*"
capture="camera"
:model-value="form.storePicture"
:after-read="posPhotosRead"
preview-size="2.13333rem"
@delete="deletePosPhotos">
</van-uploader>
</template>
</van-field>
</div>
<!-- 门店类型选择 -->
<van-field label-width="150px"
label-position="top"
label="门店类型:"
:model-value="form.selectedType"
placeholder="请选择">
<template #input>
<van-uploader :max-count="2"
accept="image/*"
v-model="form.posPhotos"
:after-read="posPhotosRead"
preview-size="120"
@delete="deletePosPhotos">
</van-uploader>
<el-select v-model="form.selectedType"
placeholder="请选择">
<el-option v-for="item in typeOptions"
:label="item.text"
:value="item.value" />
</el-select>
</template>
</van-field>
</div>
<!-- 门店类型选择 -->
<van-field :model-value="form.selectedType.join('')"
label="门店类型"
label-align="top"
placeholder="请选择"
@click="showTypePopup = true" />
<van-popup v-model:show="showTypePopup"
position="bottom"
@close="showTypePopup = false">
<van-picker v-model="form.selectedType"
:columns="typeOptions"
@confirm="handleTypeConfirm"
@cancel="showTypePopup = false" />
</van-popup>
<!-- <van-field :model-value="form.selectedType.join('')"
readonly
label="门店类型"
label-align="top"
placeholder="请选择"
@click="showTypePopup = true"
:rules="[{ required: true, message: '请选择门店类型' }]" />
<van-popup v-model:show="showTypePopup"
position="bottom"
@close="showTypePopup = false">
<van-picker v-model="form.selectedType"
:columns="typeOptions"
@confirm="handleTypeConfirm"
@cancel="showTypePopup = false" />
</van-popup> -->
</van-form>
</div>
</div>
<!-- 操作按钮 -->
<div class="button-group">
......@@ -54,11 +72,6 @@
@click="handleCreateTask">
创建任务
</van-button>
<van-button type="info"
block
@click="handleCancel">
取消
</van-button>
</div>
</div>
</div>
......@@ -68,72 +81,60 @@
import { uploadFileToOSSAPI } from '@/api'
import { v4 as uuidv4 } from 'uuid';
import { typeOptions as typeOption } from '@/views/mobile/constant'
import useUserStore from '@/store/modules/user'
const router = useRouter();
const form = ref({
selectedType: []
const form = reactive({
storeName: '',
storePicture: [],
selectedType: ''
})
const terminalName = ref('');
const headerPhotoUrl = ref('');
const typeOptions = ref(typeOption); // 门店类型
const selectedType = ref('');
const showTypePopup = ref(false);
// 门头照上传逻辑
// POS 两张照片
const posPhotosRead = async (file) => {
// 处理上传的文件
const date = new Date()
const month = date.getMonth() + 1
const theDate = date.getDate()
const pictureUrl = await uploadFileToOSSAPI(`risk/${date.getFullYear()}-${month}/${theDate}/${planId.value}/${employeeNo}/${uuidv4()}.png`, file.file)
// 判断 objectUrl
const index = form.value.posPhotos.findIndex(o => o.objectUrl)
form.value.posPhotos[index] = {
const pictureUrl = await uploadFileToOSSAPI(`risk/newTerminal-storePhoto/${date.getFullYear()}-${month}/${useUserStore().empInfo.empNo}/${uuidv4()}.png`, file.file)
form.storePicture = [{
url: pictureUrl
}
}]
showNotify({ type: 'success', message: '照片上传成功' })
}
// 删除 照片
// 删除照片
const deletePosPhotos = async () => {
if (isInitializing.value) return
await createExamine({
id: form.value.id,
posPhotos: form.value.posPhotos.map(o => o.url),
employeeId: userStore().userInfo.userId, // 稽查人id
employeeName: userStore().userInfo.nickName, // 稽查人名字
employeeNo: employeeNo, // 稽查人工号
})
showNotify({ type: 'success', message: 'POS 照片删除成功' })
form.storePicture = []
showNotify({ type: 'success', message: '照片删除成功' })
}
// 确认门店类型
const handleTypeConfirm = (val) => {
form.selectedType = val;
showTypePopup.value = false;
};
// const handleTypeConfirm = ({ selectedValues }) => {
// form.selectedType = selectedValues;
// showTypePopup.value = false;
// };
// 创建任务(可根据需求对接接口)
// 创建任务(跳转路由传参即可)
const myFormRef = ref(null)
const handleCreateTask = () => {
console.log('创建任务:', {
terminalName: terminalName.value,
headerPhoto: headerPhotoUrl.value,
storeType: selectedType.value,
});
// 此处可补充接口请求逻辑
// 校验整个表单
myFormRef.value.validate().then(() => {
// 校验通过,执行创建任务逻辑
router.push({
path: '/inspectionTask',
query: {
taskStatus: true,
storeName: form.storeName,
storeCode: null,
storePicture: form.storePicture[0]?.url,
selectedType: form.selectedType
}
})
})
};
// 取消操作
const handleCancel = () => {
console.log('取消操作');
// 可重置表单等逻辑
terminalName.value = '';
headerPhotoUrl.value = '';
selectedType.value = 'KA';
};
</script>
<style lang="scss"
......
......@@ -37,7 +37,7 @@
</template>
<template #label>
<div class="item-company">{{ item.dealersName }}</div>
<div class="item-address">{{ item.storeAddr }}</div>
<div class="item-address">{{ item.address }}</div>
</template>
</van-cell>
</van-cell-group>
......@@ -56,6 +56,9 @@
<script setup>
import { getTerminalStoreListAPI } from '@/api'
defineOptions({
name: 'Sales_point_inspection'
})
const router = useRouter();
......@@ -177,42 +180,42 @@ const addNewTerminal = () => {
}
.van-pull-refresh {
min-height: 100vh;
.result-list {
background-color: transparent;
padding: 0 20px;
margin-top: 10px;
.van-cell-group {
margin: 0;
.result-list {
background-color: transparent;
.result-item {
background-color: white;
margin-bottom: 10px;
.item-title {
font-weight: 600;
color: #333;
margin-bottom: 4px;
}
.item-company {
font-size: 14px;
color: #a6a4a4;
margin-bottom: 2px;
}
.item-address {
font-size: 13px;
color: #a6a4a4;
line-height: 1.4;
padding: 0 20px;
margin-top: 10px;
.van-cell-group {
margin: 0;
background-color: transparent;
.result-item {
background-color: white;
margin-bottom: 10px;
.item-title {
font-weight: 600;
color: #333;
margin-bottom: 4px;
}
.item-company {
font-size: 14px;
color: #a6a4a4;
margin-bottom: 2px;
}
.item-address {
font-size: 13px;
color: #a6a4a4;
line-height: 1.4;
}
}
}
}
}
.empty-tip {
......
......@@ -3,91 +3,176 @@
<!-- 任务列表 -->
<van-nav-bar left-arrow
@click-left="router.back()">
<template #right>
<span class="search-text"
@click="showSearch = true">搜索</span>
</template>
</van-nav-bar>
<van-list v-model:loading="loading"
:finished="finished"
finished-text="没有更多结果了"
class="result-list">
<van-cell-group inset>
<van-cell v-for="(item, index) in resultList"
:key="index"
class="result-item"
@click="handleClickStore(item)">
<template #title>
<div class="item-title">
<span>{{ item.name }}</span>
<span>{{ item.code }}</span>
</div>
<van-pull-refresh v-model="refreshLoading"
:pull-distance="100"
success-text="刷新成功"
@refresh="onRefresh">
<van-list v-model:loading="loading"
:finished="finished"
finished-text="没有更多结果了"
class="result-list"
@load="onLoadMore">
<van-cell-group inset>
<!-- <van-swipe-cell v-for="(item, index) in resultList"
:key="index"> -->
<van-cell v-for="(item, index) in resultList"
:key="index"
@click="handleClickStore(item)"
class="result-item">
<template #title>
<div class="item-title">
<span>{{ item.storeName }}</span>
<span>{{ parseTime(item.createTime, '{y}-{m}-{d}') }}</span>
</div>
</template>
<template #label>
<div class="item-company">{{ item.storeCode }}</div>
<div class="item-address">{{ item.address }}</div>
</template>
</van-cell>
<template #right>
<van-button square
type="danger"
text="删除"
@click="deleteFn(item, index)" />
</template>
<template #label>
<div class="item-company">{{ item.company }}</div>
<div class="item-address">{{ item.address }}</div>
</template>
</van-cell>
</van-cell-group>
</van-list>
<!-- </van-swipe-cell> -->
</van-cell-group>
</van-list>
</van-pull-refresh>
<!-- 搜索 -->
<van-popup v-model:show="showSearch"
position="right"
class="wrap">
<van-nav-bar title="筛选条件" />
<van-field type="text">
<template #input>
<van-search v-model="query.storeName"
placeholder="输入搜索的勤策终端编码/名称"
@update:model-value="search"
class="search-bar" />
</template>
</van-field>
<!-- 日期区间 -->
<van-field type="text">
<template #input>
<el-date-picker v-model="query.operDate"
type="date"
value-format="YYYY-MM-DD"
placeholder="输入搜索的日期"
@change="getInspectionTaskListFn" />
</template>
</van-field>
<!-- 重置按钮 -->
<van-button icon="replay"
class="reset-btn"
block
@click="resetFn">重置</van-button>
</van-popup>
</div>
</template>
<script setup>
import { getInspectionTaskListAPI} from '@/api'
import { parseTime } from '@/utils'
import { showNotify } from 'vant';
defineOptions({
name: 'Sales_point_inspection'
})
const router = useRouter();
const resultList = ref([
{
name: '门店1',
code: '123456',
company: '公司1',
address: '地址1'
},
{
name: '门店2',
code: '123457',
company: '公司2',
address: '地址2'
},
{
name: '门店3',
code: '123458',
company: '公司3',
address: '地址3'
},
])
// 搜索
const showSearch = ref(false)
// 获取列表
const query = reactive({
pageNum: 1,
pageSize: 10
})
const resultList = ref([])
const loading = ref(false);
const finished = ref(true);
const showEmpty = ref(false);
// 搜索处理
const handleSearch = () => {
if (!searchVal.value.trim()) {
resultList.value = mockData;
showEmpty.value = false;
return;
}
// 模拟加载状态
loading.value = true;
const refreshLoading = ref(false)
const getInspectionTaskListFn = async () => {
const res = await getInspectionTaskListAPI(query)
resultList.value = [...resultList.value, ...res.data.rows]
finished.value = res.data.total <= resultList.value.length
}
getInspectionTaskListFn()
// 模拟接口请求延迟
setTimeout(() => {
const filtered = mockData.filter(item => {
const matchStr = `${item.name}${item.code}${item.company}${item.address}`;
return matchStr.includes(searchVal.value);
});
// 刷新
const onRefresh = async () => {
refreshLoading.value = true
query.pageNum = 1
query.storeName = ''
resultList.value = []
await getInspectionTaskListFn()
refreshLoading.value = false
}
// 更多
const onLoadMore = async () => {
query.pageNum++
await getInspectionTaskListFn()
loading.value = false
}
resultList.value = filtered;
loading.value = false;
finished.value = true;
}, 500);
};
// 搜索中重置
const resetFn = () => {
query.pageNum = 1
query.storeName = ''
query.operDate = ''
resultList.value = []
getInspectionTaskListFn()
}
// 门店点击
const handleClickStore = (item) => {
router.push({
path: '/inspectionTask',
query: {
storeName: item.name,
storeCode: item.code
storeName: item.storeName,
storeCode: item.storeCode,
storePicture: item.storePictures?.split(",")[0]
}
})
}
// 路由离开守卫:控制是否缓存
onBeforeRouteLeave((to, from, next) => {
if (to.path === '/audit_activity/sales_point_inspection') {
// 强制刷新当前组件
resetFn()
}
next()
})
// 搜索地址
const search = () => {
resultList.value = []
getInspectionTaskListFn()
}
// 删除任务
const deleteFn = async (item, index) => {
// console.log(item)
// await deleteInspectionTaskAPI({
// rstdId: item.rstId
// })
// resultList.value.splice(index, 1)
// showNotify({
// message: '删除成功',
// type: 'success',
// })
}
</script>
<style scoped
......@@ -101,41 +186,89 @@ const handleClickStore = (item) => {
background-color: #f5f5f5;
min-height: 100vh;
.result-list {
background-color: transparent;
padding: 0 20px;
margin-top: 10px;
.search-text {
color: var(--main-color);
}
.van-cell-group {
margin: 0;
.van-pull-refresh {
min-height: 100vh;
.result-list {
background-color: transparent;
padding: 0 20px;
margin-top: 10px;
.result-item {
background-color: white;
margin-bottom: 10px;
.van-cell-group {
margin: 0;
background-color: transparent;
.result-item {
background-color: white;
margin-bottom: 10px;
.item-title {
font-weight: 600;
color: #333;
margin-bottom: 4px;
display: flex;
justify-content: space-between;
span:last-child {
width: 100px;
text-align: right;
display: inline-block;
}
}
.item-company {
font-size: 14px;
color: #a6a4a4;
margin-bottom: 2px;
}
.item-address {
font-size: 13px;
color: #a6a4a4;
line-height: 1.4;
}
.item-title {
font-weight: 600;
color: #333;
margin-bottom: 4px;
display: flex;
justify-content: space-between;
}
.item-company {
font-size: 14px;
color: #a6a4a4;
margin-bottom: 2px;
}
.item-address {
font-size: 13px;
color: #a6a4a4;
line-height: 1.4;
/* 滑动右侧按钮 */
::v-deep(.van-swipe-cell__right) {
height: 100px;
.van-button {
height: 100%;
}
}
}
}
}
/* 搜索 */
.wrap {
--van-field-label-width: 80px;
height: 100vh;
width: 85% !important;
.van-cell {
align-items: center;
.search-bar {
width: 100%;
padding: 0;
}
::v-deep(.el-input) {
width: 100%;
}
}
}
}
</style>
\ No newline at end of file
......@@ -5,10 +5,10 @@
@click-left="clickBack()"
fixed
placeholder>
<template #right
v-if="!isCityManager">
<template #right>
<p class="van-nav-bar__text"
@click="clickExamine()">
@click="clickExamine()"
v-hasRole="['fkwqjc']">
{{ (examined ? '已' : '未') + '稽查' }}
</p>
</template>
......
......@@ -21,17 +21,17 @@ export const constantMobileRoutes = [
name: 'm_menu'
},
{
path: 'promotion_plan_detail/:planId', // 详情
path: 'promotion_plan_detail/:planId', // CP 促销计划,详情页
component: () => import('@/views/mobile/pages/cp_activity/promotion/plan/detail'),
name: 'm_promotion_detail',
},
{
path: 'promotion_plan_editing/:planId?', //
path: 'promotion_plan_editing/:planId?', // CP 促销计划,增加,修
component: () => import('@/views/mobile/pages/cp_activity/promotion/plan/editing'),
name: 'm_promotion_editing',
},
{
path: 'examine/:examineId', // 促销内稽查
path: 'examine/:examineId', // CP 促销计划,稽查
component: () => import('@/views/mobile/pages/cp_activity/examine'),
name: 'm_promotion_examine',
},
......@@ -41,17 +41,17 @@ export const constantMobileRoutes = [
name: 'logistics'
},
{
path: 'newTerminal', // 新建终端门店
path: 'newTerminal', // 售点稽查_新建终端门店
component: () => import('@/views/mobile/pages/audit_activity/sales_point_inspection/examine/newTerminal'),
name: 'newTerminal'
},
{
path: 'taskList', // 稽查记录
path: 'taskList', // 售点稽查_稽查记录列表
component: () => import('@/views/mobile/pages/audit_activity/sales_point_inspection/examine/taskList'),
name: 'taskList'
},
{
path: 'inspectionTask', // 稽查任务(终端门店)
path: 'inspectionTask', // 售点稽查_稽查任务
component: () => import('@/views/mobile/pages/audit_activity/sales_point_inspection/examine/inspectionTask/index'),
name: 'inspectionTask'
},
......
......@@ -22,11 +22,6 @@ export default defineConfig(({ mode, command }) => {
host: true,
open: true,
proxy: {
'/tencent_map_api': {
target: 'https://apis.map.qq.com/ws/geocoder/v1',
changeOrigin: true,
rewrite: (p) => p.replace(/^\/tencent_map_api/, '')
},
'/dev-api': {
target: 'http://192.168.100.55:8080',
// target: 'https://sfa-qa.wxl66.cn/api',
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论