Commit fa7a5964 authored by lihui's avatar lihui

feat: 自提点

parent d2ce4b79
......@@ -79,3 +79,37 @@ exports.checkActivityDetail = async ctx => {
};
ctx.body = await req(ctx, opts);
};
// 获取自提点列表
exports.getPlaceList = async ctx => {
const url = `${ACTIVITY_URI}/marketing/background/take_place_list`;
const opts = {
url,
method: "GET"
};
ctx.body = await req(ctx, opts);
};
// 添加自提点
exports.addPlace = async ctx => {
const url = `${ACTIVITY_URI}/marketing/background/add_take_place"`;
const opts = {
url,
method: "POST",
json: true,
body: ctx.request.body
};
ctx.body = await req(ctx, opts);
};
//删除自提点
exports.deletePlace = async ctx => {
const url = `${ACTIVITY_URI}/marketing/background/delete_take_place`;
const opts = {
url,
method: "POST",
json: true,
body: ctx.request.body
};
ctx.body = await req(ctx, opts);
};
......@@ -67,6 +67,10 @@ router.get(`${API_VERSION}/marketing/background/marketing_list`, activity.getAct
router.post(`${API_VERSION}/goods/background/edit_goods`, activity.editGoodsDetail)
router.post(`${API_VERSION}/marketing/background/update_marketing`, activity.updateActivity)
router.post(`${API_VERSION}/marketing/background/marketing_info`, activity.checkActivityDetail)
//
router.get(`${API_VERSION}/marketing/background/take_place_list`, activity.getPlaceList)
router.post(`${API_VERSION}/marketing/background/add_take_place`, activity.addPlace)
router.post(`${API_VERSION}/marketing/background/delete_take_place`, activity.deletePlace)
//活动管理
router.get(`${API_VERSION}/goods/background/ota_list`, activity.getBusinessList);
......
......@@ -14,7 +14,6 @@ import { redirectToLogin } from "./utils/util";
// 处理路由权限
router.beforeResolve(async (to, from, next) => {
if (!to.meta.requireAuth) {
next();
return true;
......@@ -22,9 +21,9 @@ router.beforeResolve(async (to, from, next) => {
if (!store.state.permissions) {
const { status, user } = await fetchCurrentUser();
if (status === 'success') {
store.commit('updateUserInfo', user);
await store.dispatch('updateUserPermission', { email: user.email })
if (status === "success") {
store.commit("updateUserInfo", user);
await store.dispatch("updateUserPermission", { email: user.email });
} else {
redirectToLogin();
return false;
......@@ -32,11 +31,11 @@ router.beforeResolve(async (to, from, next) => {
}
if (!checkPathAuth(to.path)) {
router.push({name: 'Forbidden'})
router.push({ name: "Forbidden" });
} else {
next()
next();
}
})
});
createApp(App)
.use(router)
......
......@@ -107,6 +107,7 @@ export default {
ElMessage.error("加载失败");
}
},
// 时间差转时分秒
getTimeout(timeCount) {
if (timeCount > 0) {
......
<template>
<div id="map" class="mapContainer">
<!-- map -->
<div class="mapWrapper">
<div class="search" v-if="placeSearch">
<input type="text" placeholder="请输入关键字" v-model="searchKey" />
<button type="button" @click="handleSearch">搜索</button>
</div>
<div id="js-container" @drag="dragMap" class="myMap">
正在加载数据 ...
</div>
</div>
<!-- info -->
<div class="mapInfo">
<h3 class="title">拖拽选址</h3>
<ul class="info">
<li><span>经度:</span>{{ dragData.lng }}</li>
<li><span>纬度:</span>{{ dragData.lat }}</li>
<li><span>地址:</span>{{ dragData.address }}</li>
<li><span>最近的路口:</span>{{ dragData.nearestJunction }}</li>
<li><span>最近的路:</span>{{ dragData.nearestRoad }}</li>
<li><span>最近的POI:</span>{{ dragData.nearestPOI }}</li>
</ul>
</div>
</div>
</template>
<script>
import remoteLoad from "@/utils/remoteLoad.js";
export default {
name: "app",
data() {
return {
MapCityName: "北京",
dragData: {
lng: null,
lat: null,
address: null,
nearestJunction: null,
nearestRoad: null,
nearestPOI: null
}
};
},
methods: {
dragMap(data) {
this.dragData = {
lng: data.position.lng,
lat: data.position.lat,
address: data.address,
nearestJunction: data.nearestJunction,
nearestRoad: data.nearestRoad,
nearestPOI: data.nearestPOI
};
},
// 初始化地图
initMap() {
// 加载PositionPicker,loadUI的路径参数为模块名中 'ui/' 之后的部分
let AMapUI = (this.AMapUI = window.AMapUI);
let AMap = (this.AMap = window.AMap);
AMapUI.loadUI(["misc/PositionPicker"], PositionPicker => {
let mapConfig = {
zoom: 16,
cityName: this.MapCityName
};
if (this.lat && this.lng) {
mapConfig.center = [this.lng, this.lat];
}
let map = new AMap.Map("js-container", mapConfig);
// 加载地图搜索插件
AMap.service("AMap.PlaceSearch", () => {
this.placeSearch = new AMap.PlaceSearch({
pageSize: 5,
pageIndex: 1,
citylimit: true,
city: this.MapCityName,
map: map,
panel: "js-result"
});
});
// 启用工具条
AMap.plugin(["AMap.ToolBar"], function() {
map.addControl(
new AMap.ToolBar({
position: "RB"
})
);
});
// 创建地图拖拽
let positionPicker = new PositionPicker({
mode: "dragMap", // 设定为拖拽地图模式,可选'dragMap'、'dragMarker',默认为'dragMap'
map: map // 依赖地图对象
});
// 拖拽完成发送自定义 drag 事件
positionPicker.on("success", positionResult => {
// 过滤掉初始化地图后的第一次默认拖放
if (!this.dragStatus) {
this.dragStatus = true;
} else {
console.log(positionResult);
this.$emit("drag", positionResult);
}
});
// 启动拖放
positionPicker.start();
});
}
},
async created() {
console.log("niohao");
// 已载入高德地图API,则直接初始化地图
if (window.AMap && window.AMapUI) {
this.initMap();
// 未载入高德地图API,则先载入API再初始化
} else {
await remoteLoad(
`http://webapi.amap.com/maps?v=1.3&key=16fe8e3f4c4a6f4981626ef2cf7c759d`
);
await remoteLoad("http://webapi.amap.com/ui/1.0/main.js");
this.initMap();
}
}
};
</script>
<style lang="less" scoped>
.mapContainer {
height: 100%;
width: 100%;
display: flex;
flex-direction: row;
.mapWrapper {
width: 80%;
height: 500px;
.myMap {
height: 100%;
height: 500px;
}
}
.mapInfo {
width: 20%;
}
}
.g-wraper {
width: 1000px;
margin: 0 auto;
color: #666;
font-size: 16px;
line-height: 30px;
}
.m-part {
margin-bottom: 30px;
}
.m-part::after {
content: "";
display: block;
clear: both;
}
.m-part .title {
font-size: 30px;
line-height: 60px;
margin-bottom: 10px;
color: #333;
}
.m-part .mapbox {
width: 600px;
height: 400px;
margin-bottom: 20px;
float: left;
}
.m-part .info {
margin: 0;
padding: 0;
list-style: none;
line-height: 30px;
margin-left: 620px;
}
.m-part .info span {
display: block;
color: #999;
}
.m-part ol {
line-height: 40px;
margin-left: 0;
padding-left: 0;
}
.m-part pre {
padding: 10px 20px;
line-height: 30px;
border-radius: 3px;
box-shadow: 0 0 15px rgba(0, 0, 0, 0.5);
}
.m-footer {
background: #eee;
line-height: 60px;
text-align: center;
color: #999;
font-size: 12px;
}
.m-footer a {
margin: 0 5px;
color: #999;
text-decoration: none;
}
</style>
<template>
<div class="spellOrderSet">
<span class="demonstration">拼单起止时间: </span>
<el-date-picker
v-model="value1"
type="datetimerange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="defaultTime"
>
</el-date-picker>
</div>
<div>
<el-card>
<span>自提点设置</span>
<el-form ref="form" :model="selfLiftingPoint" label-width="80px">
<el-form-item>
<el-input
class="set"
v-model="selfLiftingPoint"
placeholder="自提点名称/自提点联系人"
suffix-icon="el-icon-search"
></el-input>
<el-button type="primary" @click="dialogFormVisible = true"
>添加自提点</el-button
>
</el-form-item>
<span class="checked">已选</span>
<el-table
class="tabList"
ref="multipleTable"
:data="tableData"
border
tooltip-effect="dark"
style="width: 80%"
@selection-change="handleSelectionChange"
>
<el-table-column align="center" type="selection" width="80">
</el-table-column>
<el-table-column label="自提点名称" align="center" width="width">
<template #default="scope">{{ scope.row.date }}</template>
</el-table-column>
<el-table-column
prop="name"
align="center"
label="位置"
width="width"
>
</el-table-column>
<el-table-column
prop="name"
align="center"
label="详细地址"
width="width"
>
</el-table-column>
<el-table-column
prop="name"
align="center"
label="自提点联系人"
width="width"
>
</el-table-column>
<el-table-column
prop="name"
align="center"
label="操作"
width="width"
>
<template #default="scope">
<el-button
type="primary"
size="small"
@click="handleModify(scope.row)"
>修改</el-button
<div class="contener">
<!-- 时间选择器 -->
<div class="spellOrderSet">
<!-- 时间选择器 -->
<span class="demonstration">拼单起止时间: </span>
<el-date-picker
v-model="startDate"
type="datetime"
minTime="startMinTime"
maxTime="startMaxTime"
placeholder="选择日期时间"
@change="changeStartTime"
>
</el-date-picker>
<el-date-picker
v-model="endDate"
type="datetime"
minTime="endMinTime"
maxTime="MaxTime"
placeholder="选择日期时间"
@change="changeEndTime"
>
</el-date-picker>
<!-- 自提点列表 -->
<div
class="card-wrapper"
v-loading="pageLoading"
element-loading-text="拼命加载中"
element-loading-spinner="el-icon-loading"
element-loading-background="rgba(0, 0, 0, 0.8)"
>
<el-card class="card-block">
<span>自提点设置</span>
<el-form ref="form" :model="selfLiftingPoint" label-width="80px">
<el-form-item>
<el-input
class="set"
v-model="selfLiftingPoint"
placeholder="自提点名称/自提点联系人"
suffix-icon="el-icon-search"
></el-input>
<el-button type="primary" @click="dialogFormVisible = true"
>添加自提点</el-button
>
</el-form-item>
<span class="checked">已选</span>
<!-- 自提点列表 -->
<el-table
class="tabList"
ref="multipleTable"
:data="takePlacelist"
border
tooltip-effect="dark"
style="width: 100%"
@selection-change="handleSelectionChange"
>
<el-table-column align="center" type="selection" width="80">
</el-table-column>
<el-table-column
prop="name"
label="自提点名称"
align="center"
width="width"
>
</el-table-column>
<el-table-column
prop="location"
align="center"
label="位置"
width="width"
>
<el-popconfirm title="确定要删除此自提点吗?">
<template #reference>
</el-table-column>
<el-table-column
prop="address"
align="center"
label="详细地址"
width="width"
>
</el-table-column>
<el-table-column
prop="contacts"
align="center"
label="自提点联系人"
width="width"
>
</el-table-column>
<el-table-column
prop="name"
align="center"
label="操作"
width="width"
>
<template #default="scope">
<el-button
type="primary"
size="small"
@click="handleDelete(scope.row)"
>删除</el-button
@click="handleModify(scope.row)"
>修改</el-button
>
<el-popconfirm
title="确定要删除此自提点吗?"
@confirm="deleteTakePlace"
>
<template #reference>
<el-button
type="primary"
size="small"
@click="handleDelete(scope.row)"
>删除</el-button
>
</template>
</el-popconfirm>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</el-form>
<!-- 添加自提点 -->
<el-dialog
title="添加自提点"
v-model="dialogFormVisible"
:show-close="false"
>
<el-form style="margin-left: 70px" :model="form">
<el-form-item label="自提点名称" :label-width="formLabelWidth">
<el-input
class="dialog-input"
v-model="form.name"
maxlength="30"
show-word-limit
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="位置" :label-width="formLabelWidth">
<el-input
class="dialog-input"
v-model="form.location"
placeholder=""
></el-input>
<a href="javascript:;" style="margin-left: 30px">从高德获取坐标</a>
</el-form-item>
<p class="location">北京市朝阳区酒仙桥9号恒通国际创新园</p>
<el-form-item label="详细地址" :label-width="formLabelWidth">
<el-input class="dialog-input" v-model="model"></el-input>
</el-form-item>
<el-form-item label="自提点联系人" :label-width="formLabelWidth">
<el-input
class="dialog-input"
v-model="model"
maxlength="30"
show-word-limit
></el-input>
</el-form-item>
<el-form-item label="联系电话" :label-width="formLabelWidth">
<el-input class="dialog-input" v-model="model"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="dialogFormVisible = false"
>保 存</el-button
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination-wrapper">
<el-pagination
background
layout="prev, pager, next"
:total="pageCount"
:page-size="5"
@current-change="handleCurrentChange"
>
</el-pagination>
</div>
</el-form>
<!-- 添加自提点 -->
<el-dialog
title="添加自提点"
v-model="dialogFormVisible"
:show-close="false"
>
<el-form
style="margin-left: 70px"
:model="form"
:rules="rules"
ref="ruleForm"
>
<el-button @click="dialogFormVisible = false">取 消</el-button>
</span>
</template>
</el-dialog>
</el-card>
<el-form-item
label="自提点名称"
prop="name"
:label-width="formLabelWidth"
>
<el-input
class="dialog-input"
v-model="form.name"
maxlength="30"
show-word-limit
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
label="位置"
prop="location"
:label-width="formLabelWidth"
>
<el-input
class="dialog-input"
v-model="form.location"
placeholder=""
></el-input>
<a href="javascript:;" style="margin-left: 30px"
>从高德获取坐标</a
>
</el-form-item>
<p class="location">北京市朝阳区酒仙桥9号恒通国际创新园</p>
<el-form-item
prop="address"
label="详细地址"
:label-width="formLabelWidth"
>
<el-input
class="dialog-input"
v-model="form.address"
></el-input>
</el-form-item>
<el-form-item
label="自提点联系人"
prop="contacts"
:label-width="formLabelWidth"
>
<el-input
class="dialog-input"
v-model="form.contacts"
maxlength="30"
show-word-limit
></el-input>
</el-form-item>
<el-form-item
prop="phone"
type="tel"
label="联系电话"
:label-width="formLabelWidth"
>
<el-input class="dialog-input" v-model="form.phone"></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="saveTakePlace"
>保 存</el-button
>
<el-button @click="dialogFormVisible = false">取 消</el-button>
</span>
</template>
</el-dialog>
</el-card>
<!-- 地图 dialog -->
<el-dialog
custom-class="mapDialog"
title="提示"
v-model="mapDialogVisible"
width="100%"
:before-close="handleClose"
>
<my-map class="my-map" />
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false"
>确 定</el-button
>
</span>
</template>
</el-dialog>
</div>
</div>
</div>
</template>
<script>
import ActivityService from "@/service/Activity/index";
import { ElMessage } from "element-plus";
import myMap from "../components/myMap.vue";
export default {
data() {
return {
startDate: "", //开始时间
endDate: "", // 结束时间
startMinTime: "", // 开始时间的最小选择时间
startMaxTime: "", // 开始时间的最大选择时间
mapDialogVisible: false,
pageLoading: false,
value1: "",
defaultTime: [
new Date(2000, 1, 1, 12, 0, 0),
new Date(2000, 2, 1, 8, 0, 0),
new Date(2000, 2, 1, 8, 0, 0)
],
selfLiftingPoint: "",
tableData: [],
rules: {
name: [
{ required: true, message: "请输入自提点名称", trigger: "blur" },
{ min: 0, max: 30, message: "长度在 0 到 30 个字符", trigger: "blur" }
],
location: [{ required: true, message: "请输入位置", trigger: "blur" }],
address: [
{ required: true, message: "请输入详细地址", trigger: "blur" }
],
contacts: [
{ required: true, message: "请输入联系人", trigger: "blur" },
{ min: 0, max: 30, message: "长度在 0 到 30 个字符", trigger: "blur" }
],
phone: [
{
required: true,
message: "请输入电话",
trigger: "blur"
}
]
},
selfLiftingPoint: "", // 自提点搜索关键词
offset: 0, // 偏移量
limit: 5, // 每页条数
page: 1, //当前页码
id: "", // 删除自提点id
pageCount: 0, // 总条数
takePlacelist: [], // 自提点列表
multipleSelection: [],
dialogFormVisible: false,
formLabelWidth: "120px",
form: {},
form: {
name: "",
location: "",
address: "",
contacts: "",
phone: ""
} // 添加自提点 详细信息
};
},
components: {
myMap
},
methods: {
/* API */
// 获取自提点
async getPlaceList() {
this.offset = (this.page - 1) * this.limit;
let params = {
keywords: this.selfLiftingPoint, //搜索关键词
offset: this.offset, // 偏移量
limit: this.limit // 每页条数
};
try {
this.pageLoading = true;
let data = await ActivityService.getPlaceList(params);
this.pageLoading = false;
this.setTableListData(data.data.list);
this.pageCount = data.data.total;
} catch {
this.pageLoading = false;
ElMessage.error("加载失败");
}
},
/* API */
// 删除自提点
async deletePlace() {
let params = {
take_place_id: this.id //搜索关键词
};
try {
this.pageLoading = true;
await ActivityService.deletePlace(params);
this.pageLoading = false;
} catch {
this.pageLoading = false;
ElMessage.error("删除失败");
}
},
// 添加自提点
async addPlace() {
let params = Object.assign(this.form, {
take_place_id: this.id //搜索关键词
});
try {
this.pageLoading = true;
await ActivityService.addPlace(params);
this.pageLoading = false;
} catch {
this.pageLoading = false;
ElMessage.error("添加失败");
}
},
// tableList数据格式转换
setTableListData(data) {
this.takePlacelist = data.map(item => {
return {
name: item.take_place_name,
location: item.province + item.city + item.area, // p + c + a
address: item.address,
contacts: item.contact_name,
id: item.take_place_id
};
});
},
// 删除自提点操作
handleDelete(val) {
this.id = val.id;
},
// 保存自提点操作
saveTakePlace() {
this.$refs.ruleForm.validate(async valid => {
if (valid) {
await this.addPlace();
this.dialogFormVisible = false;
} else {
console.log("error submit!!");
return false;
}
});
},
// 确认删除自提点操作
async deleteTakePlace() {
await this.deletePlace();
await this.getPlaceList();
},
// 更改页数
handleCurrentChange(val) {
this.page = val;
this.getPlaceList();
},
// 复选框
handleSelectionChange(val) {
this.multipleSelection = val;
},
//改变开始时间
changeStartTime() {
this.$emit("getStartTime", this.startDate);
},
// 改变结束时间
changeEndTime() {
this.$emit("getEndTime", this.endDate);
}
},
async created() {
// 初始化时间
this.startMinTime = ""; // 开始时间的最小选择时间
this.startMaxTime = ""; // 开始时间的最大选择时间
this.getPlaceList();
}
};
</script>
<style lang="less" scope>
.card-wrapper {
width: 100%;
//height: 500px;
.card-block {
width: 100%;
}
.pagination-wrapper {
height: 60px;
display: flex;
justify-content: center;
align-items: center;
}
}
.spellOrderSet {
text-align: center;
margin: 50px 0;
......@@ -181,10 +437,6 @@ export default {
}
.tabList {
margin-top: 10px;
margin-left: 75px;
}
.checked {
margin-left: 80px;
}
.dialog-input {
width: 50%;
......@@ -198,4 +450,12 @@ export default {
justify-content: center;
align-items: center;
}
</style>
// mapDialog
.mapDialog {
height: 80%;
margin-top: 10vh !important;
.my-map {
height: 100%;
}
}
</style>
......@@ -41,12 +41,12 @@ export default {
components: {
infoEditing,
addProduc,
spellOrderSet,
spellOrderSet
},
data() {
return {
active: 1, // 步骤条状态
infoEditArr: [], // 信息编辑数据
active: 3, // 步骤条状态
infoEditArr: [] // 信息编辑数据
};
},
......@@ -81,9 +81,9 @@ export default {
// 确认发布
confirmRelease() {
this.$router.push({ path: "/op/activity/manage" });
},
}
},
created() {},
created() {}
};
</script>
......@@ -111,11 +111,11 @@ export default {
}
.content,
.stepsBtn {
width: 64%;
width: 100%;
margin: 20px auto;
}
.stepsBtn {
text-align: center;
margin-top: 50px;
}
</style>
\ No newline at end of file
</style>
......@@ -58,6 +58,39 @@ class ActivityService {
);
return res;
}
// 获取自提点列表
static async getPlaceList(params) {
const res = await axios.get(
"/api/v1/marketing/background/take_place_list",
{
params
}
);
return res;
}
// 添加自提点
static async addPlace(query) {
const res = await axios.post(
"/api/v1/marketing/background/add_take_place",
{
...query
}
);
return res;
}
//删除自提点
static async deletePlace(query) {
const res = await axios.post(
"/api/v1/marketing/background/delete_take_place",
{
...query
}
);
return res;
}
}
export default ActivityService;
export default function remoteLoad(url, hasCallback) {
return createScript(url);
/**
* 创建script
* @param url
* @returns {Promise}
*/
function createScript(url) {
let scriptElement = document.createElement("script");
document.body.appendChild(scriptElement);
let promise = new Promise((resolve, reject) => {
scriptElement.addEventListener(
"load",
e => {
removeScript(scriptElement);
if (!hasCallback) {
resolve(e);
}
},
false
);
scriptElement.addEventListener(
"error",
e => {
removeScript(scriptElement);
reject(e);
},
false
);
if (hasCallback) {
window.____callback____ = function() {
resolve();
window.____callback____ = null;
};
}
});
if (hasCallback) {
url += "&callback=____callback____";
}
scriptElement.src = url;
return promise;
}
/**
* 移除script标签
* @param scriptElement script dom
*/
function removeScript(scriptElement) {
document.body.removeChild(scriptElement);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment