1.0版本

This commit is contained in:
xiaowang 2025-08-18 00:04:55 +08:00
parent fd043bb9f2
commit 6d06a72689
14 changed files with 912 additions and 137 deletions

View File

@ -30,13 +30,13 @@ public class TagInfoController {
respVO.setMsg("标签信息不能为空"); respVO.setMsg("标签信息不能为空");
return respVO; return respVO;
} }
if (tagInfoService.saveTagInfo(tagDO) == 0) { if (!tagInfoService.save(tagDO)) {
respVO.setCode(500); respVO.setCode(500);
respVO.setMsg("保存标签信息失败"); respVO.setMsg("保存标签信息失败");
return respVO; return respVO;
} }
respVO.setCode(200); respVO.setCode(200);
respVO.setData(tagInfoService.saveTagInfo(tagDO)); respVO.setData("保存标签信息成功");
return respVO; return respVO;
} }
@ -48,7 +48,7 @@ public class TagInfoController {
respVO.setMsg("标签id不能为空"); respVO.setMsg("标签id不能为空");
return respVO; return respVO;
} }
TagDO tagInfoById = tagInfoService.getTagInfoById(id); TagDO tagInfoById = tagInfoService.getById(id);
if (tagInfoById == null) { if (tagInfoById == null) {
respVO.setCode(500); respVO.setCode(500);
respVO.setMsg("查询标签信息失败"); respVO.setMsg("查询标签信息失败");
@ -62,7 +62,7 @@ public class TagInfoController {
} }
@PostMapping("/deleteById") @PostMapping("/deleteById")
public RespVO deleteTagInfoById(@RequestBody Long id) { public RespVO deleteTagInfoById(Long id) {
RespVO respVO = new RespVO(); RespVO respVO = new RespVO();
if (id == null) { if (id == null) {
@ -70,19 +70,18 @@ public class TagInfoController {
respVO.setMsg("标签id不能为空"); respVO.setMsg("标签id不能为空");
return respVO; return respVO;
} }
TagDO tagInfoById = tagInfoService.getTagInfoById(id); boolean i = tagInfoService.removeById(id);
if (tagInfoById == null) { if (!i) {
respVO.setCode(500); respVO.setCode(500);
respVO.setMsg("查询标签信息失败"); respVO.setMsg("删除标签信息失败");
return respVO; return respVO;
} }
respVO.setCode(200); respVO.setCode(200);
respVO.setData(tagInfoById); respVO.setData("删除标签信息成功");
return respVO; return respVO;
} }
@PostMapping("/updateById") @PostMapping("/updateById")
public RespVO updateTagInfoById(@RequestBody TagDO tagDO) { public RespVO updateTagInfoById(@RequestBody TagDO tagDO) {
RespVO respVO = new RespVO(); RespVO respVO = new RespVO();
@ -91,14 +90,14 @@ public class TagInfoController {
respVO.setMsg("标签信息不能为空"); respVO.setMsg("标签信息不能为空");
return respVO; return respVO;
} }
TagDO tagInfoById = tagInfoService.getTagInfoById(tagDO.getId()); Boolean i = tagInfoService.updateById(tagDO);
if (tagInfoById == null) { if (!i) {
respVO.setCode(500); respVO.setCode(500);
respVO.setMsg("查询标签信息失败"); respVO.setMsg("更新标签信息失败");
return respVO; return respVO;
} }
respVO.setCode(200); respVO.setCode(200);
respVO.setData(tagInfoById); respVO.setData("更新标签信息成功");
return respVO; return respVO;
} }
@ -106,7 +105,7 @@ public class TagInfoController {
@GetMapping("/getAll") @GetMapping("/getAll")
public RespVO getAllTagInfo() { public RespVO getAllTagInfo() {
RespVO respVO = new RespVO(); RespVO respVO = new RespVO();
List<TagDO> allTagInfo = tagInfoService.getAllTagInfo(); List<TagDO> allTagInfo = tagInfoService.list();
if (allTagInfo == null || allTagInfo.isEmpty()) { if (allTagInfo == null || allTagInfo.isEmpty()) {
respVO.setCode(500); respVO.setCode(500);
respVO.setMsg("获取标签信息失败"); respVO.setMsg("获取标签信息失败");

View File

@ -30,7 +30,6 @@ public class MainInfoDO {
private String introduce; private String introduce;
/** /**
* 状态 * 状态
*
*/ */
private Integer status; private Integer status;
/** /**

View File

@ -13,43 +13,4 @@ import java.util.List;
* @Created by 21616 * @Created by 21616
*/ */
public interface TagInfoService extends IService<TagDO> { public interface TagInfoService extends IService<TagDO> {
/**
* 保存标签信息
*
* @param tagDO 标签信息
* @return 是否成功
*/
public Integer saveTagInfo(TagDO tagDO);
/**
* 根据id查询标签信息
*
* @param id 标签id
* @return 标签信息
*/
public TagDO getTagInfoById(Long id);
/**
* 根据id删除标签信息
*
* @param id 标签id
* @return 是否成功
*/
public Integer deleteTagInfoById(Long id);
/**
* 根据id更新标签信息
*
* @param tagDO 标签信息
* @return 是否成功
*/
public Integer updateTagInfoById(TagDO tagDO);
/**
* 查询所有标签信息
*
* @return 标签信息列表
*/
public List<TagDO> getAllTagInfo();
} }

View File

@ -16,45 +16,4 @@ import java.util.List;
*/ */
@Service @Service
public class TagInfoServiceImpl extends ServiceImpl<TagInfoMapper, TagDO> implements TagInfoService { public class TagInfoServiceImpl extends ServiceImpl<TagInfoMapper, TagDO> implements TagInfoService {
@Override
public Integer saveTagInfo(TagDO tagDO) {
if (tagDO == null) {
return 0;
}
try {
return this.saveTagInfo(tagDO);
} catch (Exception e) {
return 0;
}
}
@Override
public TagDO getTagInfoById(Long id) {
if (id == null) {
return null;
}
return this.getTagInfoById(id);
}
@Override
public Integer deleteTagInfoById(Long id) {
if (id == null) {
return 0;
}
return this.deleteTagInfoById(id);
}
@Override
public Integer updateTagInfoById(TagDO tagDO) {
if (tagDO == null) {
return 0;
}
return this.updateTagInfoById(tagDO);
}
@Override
public List<TagDO> getAllTagInfo() {
return this.list();
}
} }

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="tab-bar"> <div class="tab-bar">
<van-tabbar v-model="active" route :placeholder="true"> <van-tabbar v-model="active" route :placeholder="false">
<van-tabbar-item replace to="/yumi"> <van-tabbar-item replace to="/yumi">
<span>主页管理</span> <span>主页管理</span>
<template #icon="props"> <template #icon="props">
@ -15,7 +15,7 @@
<template #icon="props"> <template #icon="props">
<img :src="props.active ? icon.active : icon.inactive" /> <img :src="props.active ? icon.active : icon.inactive" />
</template></van-tabbar-item> </template></van-tabbar-item>
<van-tabbar-item replace to="/tagManPage" icon="setting-o"><span>标签管理</span> <van-tabbar-item replace to="/tagManPage" icon="setting-o"><span>标签管理</span>
<template #icon="props"> <template #icon="props">
<img :src="props.active ? icon.active : icon.inactive" /> <img :src="props.active ? icon.active : icon.inactive" />
</template></van-tabbar-item> </template></van-tabbar-item>
@ -44,4 +44,9 @@ export default {
mounted() { } mounted() { }
}; };
</script> </script>
<style lang="less" scoped></style> <style lang="less" scoped>
.tab-bar {
max-width: 800px;
margin: 0 auto;
}
</style>

View File

@ -1,7 +1,11 @@
<template> <template>
<div class="nav-bar"> <div class="nav-bar">
<van-nav-bar title="屿 ● Nail" left-text="" :placeholder="true" :safe-area-inset-top="true" z-index="50" :fixed="true"> <van-nav-bar
title="屿 ● Nail"
left-text=""
z-index="50"
:placeholder="true"
:fixed="true">
</van-nav-bar> </van-nav-bar>
</div> </div>
</template> </template>
@ -23,4 +27,10 @@ export default {
mounted() { } mounted() { }
}; };
</script> </script>
<style lang="scss" scoped></style> <style lang="less" scoped>
.nav-bar {
max-width: 800px;
margin: 0 auto;
}
</style>

View File

@ -40,4 +40,9 @@ export default {
mounted() { } mounted() { }
}; };
</script> </script>
<style lang="less" scoped></style> <style lang="less" scoped>
.tab-bar {
max-width: 800px;
margin: 0 auto;
}
</style>

View File

@ -73,6 +73,7 @@ Vue.config.productionTip = false;
// 全局挂载 axios // 全局挂载 axios
Vue.prototype.$axios = axios Vue.prototype.$axios = axios
Vue.prototype.$dialog = Dialog;
new Vue({ new Vue({
router, router,
render: (h) => h(App), render: (h) => h(App),

View File

@ -3,20 +3,80 @@
<!-- 固定顶部导航栏 --> <!-- 固定顶部导航栏 -->
<NavBar class="nav-bar" /> <NavBar class="nav-bar" />
<div class="images"> <div class="images">
<h1>轮播图区域</h1> <van-swipe class="swipe" :autoplay="2000" indicator-color="white">
<van-swipe-item v-for="(image, index) in info.headImgs" :key="index">
<img fill="contain" v-lazy="image.url" />
</van-swipe-item>
</van-swipe>
</div> </div>
<div class="info"> <div class="info">
<h1>信息展示区包含店名营业时间状态地址电话图标微信图标</h1> <div class="title">
<div class="name">{{ info.name }}</div>
<div class="environment" @click="showEnvironmentPopup = true">
<span>查看店内环境</span>
</div>
</div>
<van-divider />
<div class="worktime">
<div>{{ info.status }} {{ info.worktime }}</div>
</div>
<van-divider />
<div class="location">
<div class="left">
<span style="color: black; font-size: 15px;">{{ info.location }}</span>
<br>
<van-icon name="location-o" size="12" />
<span>距您驾车或者打车8.0公里 需10分钟</span>
<br>
<van-icon name="guide-o" size="12" />
<span>距离1号线微电园站1号口步行400米 需8分钟</span>
</div>
<div class="right">
<van-icon name="wechat" size="25" @click="clickWechatAndPhone('wechat')" />
<van-icon name="phone" size="25" @click="clickWechatAndPhone('phone')" />
</div>
</div>
</div> </div>
<van-divider>新品展示</van-divider>
<div class="new"> <div class="new">
<h1>新品展示</h1> <van-swipe class="swipe" :autoplay="2000" indicator-color="white">
</div> <van-swipe-item v-for="(image, index) in info.newPortfolioImgs" :key="index">
<div class="navigation"> <img fill="contain" v-lazy="image.url" />
<h1>暂定导航组件</h1> </van-swipe-item>
</van-swipe>
</div> </div>
<van-popup v-model="showEnvironmentPopup" position="bottom" closeable style="height: 50vh;">
<div class="environment-images">
<van-swipe class="swipe" :autoplay="2000" indicator-color="white">
<van-swipe-item v-for="(image, index) in info.environmentImgs" :key="index">
<img fill="contain" v-lazy="image.url" />
</van-swipe-item>
</van-swipe>
</div>
</van-popup>
<van-overlay :show="showpublicityImg" @click="show = false">
<div class="wrapper" @click.stop>
<div class="block">
<img v-lazy="info.publicityImg.length > 0 ? info.publicityImg[0].url : ''" />
<div class="coress">
<van-icon name="add" @click="showpublicityImg = false" size="24" style="transform: rotate(45deg)"
color="white" />
</div>
</div>
</div>
</van-overlay>
<div style="height: 200px;"></div>
<!-- 固定底部TabBar --> <!-- 固定底部TabBar -->
<TabBar class="tab-bar" /> <TabBar class="tab-bar" />
</div> </div>
</template> </template>
<script> <script>
@ -31,39 +91,350 @@ export default {
props: {}, props: {},
data() { data() {
return { return {
info: {
id: 1,
headImgs: [],
guide: '距离1号线微电园站1号口步行400米 需8分钟',
wechat: '',
phone: '',
newPortfolioImgs: [],
locationImgs: [],
environmentImgs: [
],
publicityImg: [],
status: ""
},
storageUrl: 'http://xiaowangnas.com:9000/yumiartnail',
showEnvironmentPopup: false,
showpublicityImg: false,
}; };
}, },
watch: {}, watch: {},
computed: {}, computed: {},
methods: {}, methods: {
created() { }, async getInfo() {
mounted() { } const res = await this.$axios.get('/mainInfo/getMainInfo');
if (res.code == 200) {
this.id = res.data.id;
this.info.headImgs = this.convertToObjectArray(res.data.headImg.split('&&'));
this.info.name = res.data.name;
this.info.status = res.data.status == 0 ? '休息中' : '营业中';
this.info.worktime = res.data.worktime;
this.info.location = res.data.address;
this.info.wechat = res.data.wechat;
this.info.phone = res.data.phone;
this.info.locationImgs = this.convertToObjectArray(res.data.locationImg.split('&&'));
this.info.newPortfolioImgs = this.convertToObjectArray(res.data.newPortfolioImg.split('&&'));
this.info.environmentImgs = this.convertToObjectArray(res.data.environmentImg.split('&&'));
this.info.publicityImg = [{ url: this.storageUrl + res.data.publicityImg }];
}
if (this.info.publicityImg.length > 0) {
this.showpublicityImg = true;
} else {
this.showpublicityImg = false;
}
console.log(this.info);
},
convertToObjectArray(urls) {
return urls.map(url => {
if (!url) return { url: '' }; //
const modifiedUrl = this.storageUrl + url;
return { url: modifiedUrl }
});
},
convertUrlsToString(arr) {
return arr.map(item => {
let modifiedUrl = item.url.replace(this.storageUrl, '');
return modifiedUrl;
}).join('&&');
},
clickWechatAndPhone(type) {
this.$dialog.confirm({
title: type == 'wechat' ? '微信号' : '电话号码',
message: type == 'wechat' ? this.info.wechat : this.info.phone,
confirmButtonText: '一键复制',
})
.then(() => {
this.textToCopy = type == 'wechat' ? this.info.wechat : this.info.phone;
this.handleCopy();
})
.catch(() => {
// on cancel
});
},
async handleCopy() {
try {
// navigator.clipboard
if (navigator.clipboard) {
//
if ('permissions' in navigator) {
const permissionStatus = await navigator.permissions.query({ name: 'clipboard-write' });
if (permissionStatus.state === 'granted' || (permissionStatus.state === 'prompt' && await permissionStatus.request() === 'granted')) {
await navigator.clipboard.writeText(this.textToCopy);
this.$toast.success('已复制到剪贴板');
} else {
console.error('未获得剪贴板写入权限');
this.$toast.fail('未获得剪贴板写入权限,请手动复制');
}
} else {
//
await navigator.clipboard.writeText(this.textToCopy);
this.$toast.success('已复制到剪贴板');
}
} else {
// navigator.clipboard使document.execCommand
const textArea = document.createElement('textarea');
textArea.value = this.textToCopy;
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
this.$toast.success('已复制到剪贴板');
} catch (err) {
console.error('复制失败:', err);
this.$toast.fail('复制失败,请手动复制');
}
document.body.removeChild(textArea);
}
} catch (err) {
console.error('复制失败:', err);
this.$toast.fail('复制失败,请手动复制');
}
},
// localStorage
recordCurrentTime(storageKey = 'recordedTime') {
//
const currentTime = new Date().getTime();
// localStorage
localStorage.setItem(storageKey, currentTime.toString());
return currentTime;
},
// localStorage
getTimeDifference(storageKey = 'recordedTime') {
// localStorage
const storedTimeStr = localStorage.getItem(storageKey);
//
if (!storedTimeStr) {
console.error('没有找到记录的时间');
return null;
}
//
const storedTime = parseInt(storedTimeStr, 10);
//
if (isNaN(storedTime)) {
console.error('存储的时间格式不正确');
return null;
}
//
const currentTime = new Date().getTime();
//
const differenceInSeconds = Math.floor((currentTime - storedTime) / 1000);
return differenceInSeconds;
}
},
created() {
//
const recordedTime = localStorage.getItem('recordedTime');
if (recordedTime) {
//
const timeDifference = this.getTimeDifference();
console.log(`与上次记录的时间差为 ${timeDifference}`);
if (timeDifference >= 60 * 60 * 24) {
// 24
this.recordCurrentTime();
this.showpublicityImg = true;
} else {
// 24
console.log('在24小时内');
this.showpublicityImg = false;
}
} else {
console.log('没有找到记录的时间');
}
},
mounted() {
this.getInfo();
},
beforeDestroy() {
//
this.showEnvironmentPopup = false;
this.showpublicityImg = false;
this.recordCurrentTime();
}
}; };
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@base-bg: #f9fafb;
@card-bg: white;
@text-primary: #1f2937;
@text-secondary: #6b7280;
@accent-color: #3b82f6;
@accent-dark: #2563eb;
@danger-color: #ef4444;
@gray-light: #d1d5db;
@shadow-base: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
@shadow-active: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
.homepage { .homepage {
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
overflow: auto; overflow: auto;
max-width: 800px;
margin: 0 auto;
.images { .images {
width: 100%; width: 100%;
height: 25vh; height: 35vh;
overflow: hidden;
min-height: 200px;
max-height: 500px;
.swipe {
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
}
}
} }
.info { .info {
width: 100%; width: 100%;
height: 20vh; padding: 10px;
.title {
display: flex;
justify-content: space-between;
align-items: center;
.name {
font-size: 40px;
color: @text-primary;
font-weight: bold;
cursor: pointer;
}
.environment {
cursor: pointer;
span {
font-size: 12px;
color: #525050;
}
}
}
.location {
display: flex;
.left {
width: 70%;
span {
font-size: 12px;
color: #a19e9e;
margin-bottom: 10px;
}
}
.right {
width: 30%;
display: flex;
justify-content: space-evenly;
align-items: center;
color: #a19e9e;
}
}
} }
.new { .new {
width: 100%; display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
width: 95%;
height: 25vh;
overflow: hidden;
min-height: 200px;
max-height: 500px;
margin: auto;
border-radius: 10px;
.swipe {
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
}
}
} }
.navigation { .navigation {
width: 100%; width: 100%;
} }
.environment-images {
width: 100%;
overflow: hidden;
max-height: 500px;
.swipe {
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
}
}
}
.wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
position: relative;
width: 100%;
.block {
padding: 10px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
img {
width: 100%;
object-fit: contain;
border-radius: 10px;
}
.coress {
padding-top: 20px;
}
}
}
} }
</style> </style>

View File

@ -146,6 +146,10 @@ export default {
for (let tagID of item.tagId.split("&&")) { for (let tagID of item.tagId.split("&&")) {
tagInfo.push(this.idToObjectMap[tagID]) tagInfo.push(this.idToObjectMap[tagID])
} }
console.log(">>>>");
console.log(tagInfo);
return { return {
id: item.id, id: item.id,
title: item.title, title: item.title,
@ -346,7 +350,7 @@ export default {
// //
.cards-container { .cards-container {
padding: 0 5px; padding: 10px;
overflow: auto; overflow: auto;
// //

View File

@ -11,8 +11,11 @@
</div> </div>
<div class="info"> <div class="info">
<div class="title" @click="showpop"> <div class="title">
<div>{{ info.name }}</div> <div class="name" @click="showpop">{{ info.name }}</div>
<div class="environment" @click="showEnvironmentPopup = true">
<span>查看店内环境</span>
</div>
</div> </div>
<van-divider /> <van-divider />
<div class="worktime"> <div class="worktime">
@ -30,9 +33,8 @@
<span>距离1号线微电园站1号口步行400米 需8分钟</span> <span>距离1号线微电园站1号口步行400米 需8分钟</span>
</div> </div>
<div class="right"> <div class="right">
<van-icon name="wechat" size="25" /> <van-icon name="wechat" size="25" @click="clickWechatAndPhone('wechat')" />
<van-icon name="phone" size="25" /> <van-icon name="phone" size="25" @click="clickWechatAndPhone('phone')" />
</div> </div>
</div> </div>
</div> </div>
@ -46,7 +48,11 @@
</div> </div>
<van-popup position="bottom" v-model="show" style="height: 80%;" closeable :close-on-click-overlay="false">
<div style="height: 200px;"></div>
<van-popup position="bottom" v-model="show" closeable :close-on-click-overlay="false">
<van-form @submit="saveChangeInfo"> <van-form @submit="saveChangeInfo">
<van-field name="headImgs" label="主页店图"> <van-field name="headImgs" label="主页店图">
<template #input> <template #input>
@ -57,7 +63,8 @@
:rules="[{ required: true, message: '请填写店名' }]" /> :rules="[{ required: true, message: '请填写店名' }]" />
<van-field v-model="info.worktime" name="worktime" label="营业信息" placeholder="营业信息" <van-field v-model="info.worktime" name="worktime" label="营业信息" placeholder="营业信息"
:rules="[{ required: true, message: '请填写营业信息' }]" /> :rules="[{ required: true, message: '请填写营业信息' }]" />
<van-field readonly clickable label="营业状态" :value="info.status" placeholder="选择营业状态" @click="showPicker = true" /> <van-field readonly clickable label="营业状态" :value="info.status" placeholder="选择营业状态"
@click="showPicker = true" />
<van-popup v-model="showPicker" round position="bottom"> <van-popup v-model="showPicker" round position="bottom">
<van-picker show-toolbar :columns="columns" @cancel="showPicker = false" @confirm="onPicker" /> <van-picker show-toolbar :columns="columns" @cancel="showPicker = false" @confirm="onPicker" />
</van-popup> </van-popup>
@ -83,12 +90,38 @@
<van-uploader v-model="info.environmentImgs" :after-read="uploadEnvironmentImgs" /> <van-uploader v-model="info.environmentImgs" :after-read="uploadEnvironmentImgs" />
</template> </template>
</van-field> </van-field>
<van-field name="publicityImg" label="广告图">
<template #input>
<van-uploader v-model="info.publicityImg" :after-read="uploadPublicityImg" :max-count="1" />
</template>
</van-field>
<div style="margin: 16px;"> <div style="margin: 16px;">
<van-button round block type="info" native-type="submit">提交</van-button> <van-button round block type="info" native-type="submit">提交</van-button>
</div> </div>
</van-form> </van-form>
</van-popup> </van-popup>
<van-popup v-model="showEnvironmentPopup" position="bottom" closeable style="height: 50vh;">
<div class="environment-images">
<van-swipe class="swipe" :autoplay="2000" indicator-color="white">
<van-swipe-item v-for="(image, index) in info.environmentImgs" :key="index">
<img fill="contain" v-lazy="image.url" />
</van-swipe-item>
</van-swipe>
</div>
</van-popup>
<van-overlay :show="showpublicityImg" @click="show = false">
<div class="wrapper" @click.stop>
<div class="block">
<img v-lazy="info.publicityImg.length > 0 ? info.publicityImg[0].url : ''" />
<div class="coress">
<van-icon name="add" @click="showpublicityImg = false" size="24" style="transform: rotate(45deg)"
color="white" />
</div>
</div>
</div>
</van-overlay>
<!-- 固定底部TabBar --> <!-- 固定底部TabBar -->
@ -120,7 +153,7 @@ export default {
environmentImgs: [ environmentImgs: [
], ],
publicityImg: '', publicityImg: [],
status: "" status: ""
}, },
storageUrl: 'http://xiaowangnas.com:9000/yumiartnail', storageUrl: 'http://xiaowangnas.com:9000/yumiartnail',
@ -139,6 +172,9 @@ export default {
}, },
showPicker: false, showPicker: false,
columns: ['营业中', '休息中'], columns: ['营业中', '休息中'],
showEnvironmentPopup: false,
showpublicityImg: true,
textToCopy: '', //
}; };
}, },
watch: {}, watch: {},
@ -146,7 +182,6 @@ export default {
methods: { methods: {
async getInfo() { async getInfo() {
const res = await this.$axios.get('/mainInfo/getMainInfo'); const res = await this.$axios.get('/mainInfo/getMainInfo');
console.log(res);
if (res.code == 200) { if (res.code == 200) {
this.id = res.data.id; this.id = res.data.id;
this.info.headImgs = this.convertToObjectArray(res.data.headImg.split('&&')); this.info.headImgs = this.convertToObjectArray(res.data.headImg.split('&&'));
@ -159,7 +194,15 @@ export default {
this.info.locationImgs = this.convertToObjectArray(res.data.locationImg.split('&&')); this.info.locationImgs = this.convertToObjectArray(res.data.locationImg.split('&&'));
this.info.newPortfolioImgs = this.convertToObjectArray(res.data.newPortfolioImg.split('&&')); this.info.newPortfolioImgs = this.convertToObjectArray(res.data.newPortfolioImg.split('&&'));
this.info.environmentImgs = this.convertToObjectArray(res.data.environmentImg.split('&&')); this.info.environmentImgs = this.convertToObjectArray(res.data.environmentImg.split('&&'));
this.info.publicityImg = [{ url: this.storageUrl + res.data.publicityImg }];
} }
if (this.info.publicityImg.length > 0) {
this.showpublicityImg = true;
} else {
this.showpublicityImg = false;
}
console.log(this.info);
}, },
async saveChangeInfo() { async saveChangeInfo() {
this.show = false; this.show = false;
@ -173,6 +216,8 @@ export default {
this.saveInfo.locationImg = this.convertUrlsToString(this.info.locationImgs); this.saveInfo.locationImg = this.convertUrlsToString(this.info.locationImgs);
this.saveInfo.newPortfolioImg = this.convertUrlsToString(this.info.newPortfolioImgs); this.saveInfo.newPortfolioImg = this.convertUrlsToString(this.info.newPortfolioImgs);
this.saveInfo.environmentImg = this.convertUrlsToString(this.info.environmentImgs); this.saveInfo.environmentImg = this.convertUrlsToString(this.info.environmentImgs);
this.saveInfo.publicityImg = this.info.publicityImg.length > 0 ? this.info.publicityImg[0].url.replace(this.storageUrl, '') : '';
this.saveInfo.status = this.info.status == '营业中' ? 0 : 1;
console.log(this.saveInfo); console.log(this.saveInfo);
const res = await this.$axios.post('/mainInfo/updateMainInfo', this.saveInfo); const res = await this.$axios.post('/mainInfo/updateMainInfo', this.saveInfo);
console.log(res); console.log(res);
@ -197,6 +242,9 @@ export default {
uploadEnvironmentImgs(file) { uploadEnvironmentImgs(file) {
this.uploadImgs(file, 'environmentImgs') this.uploadImgs(file, 'environmentImgs')
}, },
uploadPublicityImg(file) {
this.uploadImgs(file, 'publicityImg')
},
// //
async uploadImgs(file, type) { async uploadImgs(file, type) {
try { try {
@ -225,9 +273,14 @@ export default {
this.info.environmentImgs.pop(); this.info.environmentImgs.pop();
this.info.environmentImgs.push({ url: result }); this.info.environmentImgs.push({ url: result });
break; break;
case 'publicityImg':
this.info.publicityImg.pop();
this.info.publicityImg.push({ url: result });
break;
default: default:
break; break;
} }
this.$toast.success('上传成功');
} catch (error) { } catch (error) {
// this.uploadResult = `: ${error.message}`; // this.uploadResult = `: ${error.message}`;
this.$toast.fail('上传失败'); this.$toast.fail('上传失败');
@ -238,6 +291,7 @@ export default {
}, },
convertToObjectArray(urls) { convertToObjectArray(urls) {
return urls.map(url => { return urls.map(url => {
if (!url) return { url: '' }; //
const modifiedUrl = this.storageUrl + url; const modifiedUrl = this.storageUrl + url;
return { url: modifiedUrl } return { url: modifiedUrl }
}); });
@ -249,9 +303,128 @@ export default {
}).join('&&'); }).join('&&');
}, },
onPicker(value) { onPicker(value) {
this.info.status = value=='营业中'?1:0; this.info.status = value == '营业中' ? 1 : 0;
this.showPicker = false; this.showPicker = false;
}, },
clickWechatAndPhone(type) {
this.$dialog.confirm({
title: type == 'wechat' ? '微信号' : '电话号码',
message: type == 'wechat' ? this.info.wechat + '\n点击一键复制后,可自动复制并跳转微信)' : this.info.phone,
confirmButtonText: '一键复制',
})
.then(() => {
this.textToCopy = type == 'wechat' ? this.info.wechat : this.info.phone;
this.handleCopy(type);
})
.catch(() => {
// on cancel
});
},
async handleCopy(type) {
try {
// navigator.clipboard
if (navigator.clipboard) {
//
if ('permissions' in navigator) {
const permissionStatus = await navigator.permissions.query({ name: 'clipboard-write' });
if (permissionStatus.state === 'granted' || (permissionStatus.state === 'prompt' && await permissionStatus.request() === 'granted')) {
await navigator.clipboard.writeText(this.textToCopy);
this.$toast.success('已复制到剪贴板');
} else {
console.error('未获得剪贴板写入权限');
this.$toast.fail('未获得剪贴板写入权限,请手动复制');
}
} else {
//
await navigator.clipboard.writeText(this.textToCopy);
this.$toast.success('已复制到剪贴板');
}
} else {
// navigator.clipboard使document.execCommand
const textArea = document.createElement('textarea');
textArea.value = this.textToCopy;
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand('copy');
this.$toast.success('已复制到剪贴板');
} catch (err) {
console.error('复制失败:', err);
this.$toast.fail('复制失败,请手动复制');
}
document.body.removeChild(textArea);
}
this.handleSpecialAction(type)
} catch (err) {
console.error('复制失败:', err);
this.$toast.fail('复制失败,请手动复制');
}
},
handleSpecialAction(type) {
//
const isWechatEnv = /MicroMessenger/i.test(navigator.userAgent);
if (type === 'wechat') {
//
if (isWechatEnv) {
this.$toast.fail('请在微信外部浏览器中打开以跳转微信');
return;
}
try {
//
const wechatLink = 'weixin://';
const startTime = Date.now();
// iframe
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = wechatLink;
document.body.appendChild(iframe);
//
setTimeout(() => {
document.body.removeChild(iframe);
if (Date.now() - startTime < 1000) {
this.$toast.fail('未检测到微信客户端,请手动打开微信');
} else {
this.$toast.info('正在打开微信...');
}
}, 800);
} catch (error) {
this.$toast.fail('打开微信失败,请手动操作');
console.error('微信跳转错误:', error);
}
} else if (type === 'phone') {
//
if (!this.info?.phone) {
this.$toast.fail('电话号码不存在');
return;
}
//
const phoneNumber = this.info.phone.replace(/\s/g, '');
if (!/^\d{11}$/.test(phoneNumber)) {
this.$toast.fail('请检查电话号码格式');
return;
}
try {
//
if (/Android|iPhone/i.test(navigator.userAgent)) {
//
window.location.href = `tel:${phoneNumber}`;
this.$toast.info(`正在拨打 ${phoneNumber}...`);
} else {
//
this.$toast.info(`电话号码: ${phoneNumber}\n请在手机上使用此功能`);
}
} catch (error) {
this.$toast.fail('拨打电话失败,请手动拨号');
console.error('拨打电话错误:', error);
}
}
}
}, },
created() { }, created() { },
mounted() { mounted() {
@ -276,10 +449,11 @@ export default {
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
overflow: auto; overflow: auto;
max-width: 800px;
margin: 0 auto;
.images { .images {
width: 100%; width: 100%;
height: 25vh; height: 35vh;
overflow: hidden; overflow: hidden;
min-height: 200px; min-height: 200px;
max-height: 500px; max-height: 500px;
@ -297,7 +471,30 @@ export default {
.info { .info {
width: 100%; width: 100%;
padding: 20px; padding: 10px;
.title {
display: flex;
justify-content: space-between;
align-items: center;
.name {
font-size: 40px;
color: @text-primary;
font-weight: bold;
cursor: pointer;
}
.environment {
cursor: pointer;
span {
font-size: 12px;
color: #525050;
}
}
}
.location { .location {
display: flex; display: flex;
@ -330,12 +527,13 @@ export default {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
overflow: hidden; overflow: hidden;
width: 90%; width: 95%;
height: 25vh; height: 25vh;
overflow: hidden; overflow: hidden;
min-height: 200px; min-height: 200px;
max-height: 500px; max-height: 500px;
margin: auto; margin: auto;
border-radius: 10px;
.swipe { .swipe {
width: 100%; width: 100%;
@ -353,6 +551,50 @@ export default {
width: 100%; width: 100%;
} }
.environment-images {
width: 100%;
overflow: hidden;
max-height: 500px;
.swipe {
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
}
}
}
.wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
position: relative;
width: 100%;
.block {
padding: 10px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
img {
width: 100%;
object-fit: contain;
border-radius: 10px;
}
.coress {
padding-top: 20px;
}
}
}
} }
</style> </style>

View File

@ -673,14 +673,14 @@ export default {
// //
.cards-container { .cards-container {
padding: 0 20px; padding: 10px;
overflow: auto; overflow: auto;
// //
.card-grid { .card-grid {
display: grid; display: grid;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
gap: 24px; gap: 10px;
// // // //
// @media (max-width: 600px) { // @media (max-width: 600px) {

View File

@ -670,14 +670,14 @@ export default {
// //
.cards-container { .cards-container {
padding: 0 20px; padding:10px;
overflow: auto; overflow: auto;
// //
.card-grid { .card-grid {
display: grid; display: grid;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
gap: 24px; gap: 10px;
// // // //
// @media (max-width: 600px) { // @media (max-width: 600px) {

View File

@ -2,14 +2,67 @@
<div class="tag-man-page"> <div class="tag-man-page">
<!-- 固定顶部导航栏 --> <!-- 固定顶部导航栏 -->
<NavBar class="nav-bar" /> <NavBar class="nav-bar" />
<!-- 内容区域 -->
<div class="content">
<div class="tag" v-for="(tag, index) in tags" :key="index">
<van-tag :color="tag.tagBgColor" :text-color="tag.tagColor" size="large">{{ tag.tagName }}</van-tag>
<div class="btn">
<van-button type="primary" size="mini" round @click="editTag(tag)">编辑</van-button>
<van-button type="danger" size="mini" round @click="deleteTag(tag)">删除</van-button>
</div>
</div>
<div style="height: 300px;" v-if="tags.length > 10"></div>
<div class="addTag">
<van-button type="primary" @click="addNewTag" block>新增标签</van-button>
</div>
</div>
<!-- 固定底部TabBar --> <!-- 固定底部TabBar -->
<ManTabBar class="tab-bar" /> <ManTabBar class="tab-bar" />
<van-popup v-model="showPopup" closeable position="bottom" style="height: 80vh; " lazy-render
:close-on-click-overlay="false">
<div class="tagModify">
<van-tag :color="editTagInfo.tagBgColor" :text-color="editTagInfo.tagColor" size="large">{{
editTagInfo.tagName }}</van-tag>
</div>
<div class="popup-content">
<van-field label="标签名" v-model="editTagInfo.tagName" placeholder="请输入标签名" />
<div class="colorChoose">
<van-field label="字色" v-model="editTagInfo.tagColor" type="color" />
<van-field label="背景色" v-model="editTagInfo.tagBgColor" type="color" />
</div>
<van-button type="primary" @click="saveChange" block>确认修改</van-button>
</div>
</van-popup>
<van-popup v-model="showaddPopup" closeable position="bottom" style="height: 80vh; " lazy-render
:close-on-click-overlay="false">
<div class="tagModify">
<van-tag :color="editTagInfo.tagBgColor" :text-color="editTagInfo.tagColor" size="large">{{
editTagInfo.tagName }}</van-tag>
</div>
<div class="popup-content">
<van-field label="标签名" v-model="editTagInfo.tagName" placeholder="请输入标签名" />
<div class="colorChoose">
<van-field label="字色" v-model="editTagInfo.tagColor" type="color" />
<van-field label="背景色" v-model="editTagInfo.tagBgColor" type="color" />
</div>
<van-button type="primary" @click="saveAdd" block>确认新增</van-button>
</div>
</van-popup>
</div> </div>
</template> </template>
<script> <script>
import NavBar from '@/components/NavBar.vue'; import NavBar from '@/components/NavBar.vue';
import ManTabBar from '@/components/ManTabBar.vue'; import ManTabBar from '@/components/ManTabBar.vue';
import { Dialog } from 'vant';
export default { export default {
name: 'TagManPage', name: 'TagManPage',
components: { components: {
@ -19,13 +72,179 @@ export default {
props: {}, props: {},
data() { data() {
return { return {
tags: [],
showPopup: false,
editTagInfo: { tagName: '', tagBgColor: '', tagColor: '' },
showaddPopup: false,
}; };
}, },
watch: {}, watch: {},
computed: {}, computed: {},
methods: {}, methods: {
getAllTags() {
this.$axios.get('/tagInfo/getAll').then(res => {
console.log(res);
if (res.code === 200) {
this.tags = res.data;
} else {
this.$toast.fail('获取标签失败');
}
}).catch(() => {
this.$toast.fail('网络错误,请稍后再试');
});
},
addTag() {
if (this.newTagName) {
this.$axios.post('/tagInfo/add', {
tagName: this.newTagName,
tagBgColor: '#f2826a',
tagColor: '#fff'
}).then(res => {
console.log(res);
if (res.code === 200) {
this.$toast.success('添加标签成功');
} else {
this.$toast.fail('添加标签失败');
}
}).catch(() => {
this.$toast.fail('网络错误,请稍后再试');
});
}
},
editTag(tag) {
this.editTagInfo = JSON.parse(JSON.stringify(tag));
this.showPopup = true;
},
deleteTag(tag) {
Dialog.confirm({
title: '确认删除标签',
message: '点击取消可继续编辑',
}).then(() => {
console.log(tag);
this.$axios.post('/tagInfo/deleteById', null, {
params: {
id: tag.id
}
}).then(res => {
console.log(res);
if (res.code === 200) {
this.$toast.success('删除标签成功');
this.getAllTags();
}
else {
this.$toast.fail('删除标签失败');
}
}).catch(() => {
this.$toast.fail('网络错误,请稍后再试');
});
})
.catch(() => {
})
console.log(tag);
},
saveChange() {
Dialog.confirm({
title: '确认保存修改',
message: '点击取消可继续编辑',
}).then(() => {
console.log(this.editTagInfo);
this.$axios.post('/tagInfo/updateById', this.editTagInfo).then(res => {
console.log(res);
if (res.code === 200) {
this.$toast.success('修改标签成功');
this.showPopup = false;
this.getAllTags();
}
else {
this.$toast.fail('修改标签失败');
}
}).catch(() => {
this.$toast.fail('网络错误,请稍后再试');
this.showPopup = false;
});
})
.catch(() => {
// on cancel
});
},
addNewTag() {
this.editTagInfo = { tagName: '标签', tagBgColor: '#f2826a', tagColor: '#fff' };
this.showaddPopup = true;
},
saveAdd() {
Dialog.confirm({
title: '确认新增标签',
message: '点击取消可继续编辑',
}).then(() => {
console.log(this.editTagInfo);
this.$axios.post('/tagInfo/save', this.editTagInfo).then(res => {
console.log(res);
if (res.code === 200) {
this.$toast.success('新增标签成功');
this.showaddPopup = false;
this.getAllTags();
}
else {
this.$toast.fail('新增标签失败');
}
}).catch(() => {
this.$toast.fail('网络错误,请稍后再试');
this.showaddPopup = false;
});
})
.catch(() => {
// on cancel
});
},
},
created() { }, created() { },
mounted() { } mounted() {
this.getAllTags();
}
}; };
</script> </script>
<style lang="less" scoped></style> <style lang="less" scoped>
.tag-man-page {
padding: 10px;
height: 100vh;
overflow: hidden;
.content {
overflow-y: auto;
height: calc(100vh - 110px);
.tag {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
padding: 10px;
.btn {
display: flex;
}
}
}
.tagModify {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 50px;
margin-top: 50px;
}
.colorChoose {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
}
</style>