Panel.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. <template>
  2. <main class="panel_main pc_none" ref="panelMainRef">
  3. <div class="panel_head_box">
  4. <span class="panel_head_btn" @click="close_panel_btn_fun"></span>
  5. <h4 class="panel_head_h4">
  6. 网站地图
  7. </h4>
  8. </div>
  9. <section class="panel_long clearfix">
  10. <div class="panel_main_in">
  11. <!-- 首页 -->
  12. <div class="panel_box" v-if="index_bool">
  13. <div class="panel_a_box ">
  14. <NuxtLink to="/" title="首页" class="panel_a_btn">
  15. 首页
  16. </NuxtLink>
  17. <NuxtLink class="panel_a_btn"
  18. v-for="(item, index) in navigation1" :key="index"
  19. @click="getLinkPath(item)"
  20. :target="item.is_url == 1 ? '_blank' : '_self'"
  21. >
  22. <span> {{ item.alias }}</span>
  23. </NuxtLink>
  24. </div>
  25. </div>
  26. <!-- 深度服务 -->
  27. <div class="panel_box" v-if="index_bool">
  28. <div class="panel_name_box">
  29. <div class="panel_name">深度服务</div>
  30. </div>
  31. <div class="panel_a_box ">
  32. <NuxtLink class="panel_a_btn"
  33. v-for="(item, index) in navigation3" :key="index"
  34. @click="getLinkPath(item)"
  35. :target="item.is_url == 1 ? '_blank' : '_self'"
  36. >
  37. <span>{{ item.alias }}</span>
  38. </NuxtLink>
  39. </div>
  40. </div>
  41. <!-- 互动平台 -->
  42. <div class="panel_box" v-if="index_bool">
  43. <div class="panel_name_box">
  44. <div class="panel_name">互动平台</div>
  45. </div>
  46. <div class="panel_a_box ">
  47. <NuxtLink class="panel_a_btn"
  48. v-for="(item, index) in navigation4" :key="index"
  49. @click="getLinkPath(item)"
  50. :target="item.is_url == 1 ? '_blank' : '_self'"
  51. >
  52. {{ item.alias }}
  53. </NuxtLink>
  54. </div>
  55. </div>
  56. <!-- 商城首页 -->
  57. <div class="panel_box" v-if="shop_bool">
  58. <div class="panel_name_box">
  59. <div class="panel_name">商城首页</div>
  60. </div>
  61. <div class="panel_a_box ">
  62. <!-- :title="item.alias" -->
  63. <!-- :to="`/xiangcunshangcheng/${item.aLIas_pinyin}/index.html`" -->
  64. <!-- /xiangcunshangcheng/nongfuchanpin/index.html?cityid=33 -->
  65. <NuxtLink
  66. class="panel_a_btn"
  67. :class="[{ 'shop_name_a_only': item.category_id == shop_category_id }]"
  68. @click="phone_panel_btn_click(item)"
  69. v-for="item in shopNav"
  70. >
  71. <!-- {{item.category_id }} -->
  72. <!-- {{item.aLIas_pinyin }} -->
  73. {{item.alias}}
  74. </NuxtLink>
  75. </div>
  76. </div>
  77. <!-- 地区选择 -->
  78. <div class="panel_box province_box" v-if="shop_bool">
  79. <div class="panel_name_box">
  80. <div class="panel_name">地区选择</div>
  81. </div>
  82. <div class="panel_a_box ">
  83. <NuxtLink
  84. class="panel_a_btn"
  85. :class="[{ 'shop_name_a_only': item.id == cityId }]"
  86. v-for="(item, index) in province_arr" :key="index"
  87. @click="phone_panel_btn_province_click(item)"
  88. >
  89. {{ item.abbreviation }}
  90. </NuxtLink>
  91. </div>
  92. </div>
  93. <!-- 确定 -->
  94. <div class="panel_foot_btn_box" v-if="shop_bool">
  95. <div class="panel_foot_btn " @click="panel_reset_fun">重置</div>
  96. <div class="panel_foot_btn" @click="panel_sure_fun">确定</div>
  97. </div>
  98. </div>
  99. </section>
  100. </main>
  101. </template>
  102. <script setup>
  103. import { fa } from 'element-plus/es/locale/index.mjs';
  104. //3.获取导航菜单 start ---------------------------------------->
  105. const navigation1 = ref([]);
  106. const navigation3 = ref([]);// 深度服务
  107. const navigation4 = ref([]);// 互动平台
  108. const province_arr = ref([]);// 省列表
  109. const shopNavOnePinyin = ref("")//获得商城导航的第一个 作为默认的跳转链接
  110. const shopNav = ref("")//获得商城导航
  111. // 引入全局状态
  112. const panelVisible = useState('panelVisible')
  113. //获得详情id
  114. const route = useRoute();
  115. const router = useRouter();
  116. // const cityId = ref("")
  117. const shop_category_id = ref("")// 商城首页
  118. const shop_category_pinyin = ref( getRoutePath(2) || "")//=商城首页=默认pinyin
  119. const shop_category_pinyin_defult = ref("")//默认=商城首页
  120. const cityId = ref(route.query.cityid || "")//默认=地区选择=当前页面的城市id=省
  121. const cityId_defult = cityId.value//默认=地区选择=当前页面的城市id=省
  122. const index_bool = ref(true)//首页
  123. const shop_bool = ref(false)//商城
  124. if(getRoutePath(1) == "xiangcunshangcheng"){//如果是商城
  125. shop_bool.value = true// 商城
  126. index_bool.value = false//首页
  127. }else{//如果不是商城
  128. shop_bool.value = false//商城
  129. index_bool.value = true//首页
  130. }
  131. // console.log("getRoutePath(1)",getRoutePath(1))
  132. // 地区选择province
  133. const phone_panel_btn_province_click = (the_item) => {
  134. // 点击btn变色
  135. cityId.value = the_item.id
  136. // setUrlParam(the_item)
  137. }
  138. // 商城首页
  139. const phone_panel_btn_click = (the_item) => {
  140. // 点击btn变色
  141. shop_category_id.value = the_item.category_id
  142. shop_category_pinyin.value = the_item.aLIas_pinyin
  143. }
  144. const targetSegment = getRoutePath(2);//返回第二层的路径id
  145. //通过导航路径反向查询导航id
  146. const getRouteId = await requestDataPromise('/web/getWebsiteRoute', {
  147. method: 'GET',
  148. query: {
  149. 'pinyin': targetSegment,
  150. },
  151. });
  152. shop_category_id.value = getRouteId.data.category_id
  153. //1.4设置url中的参数
  154. const setUrlParam = (item) => {
  155. //获得当前的url
  156. const currentUrl = window.location.href;
  157. //判断url中是否含有select参数,如果有就删掉
  158. cityId.value = item.id;
  159. // 复制当前的 query 对象
  160. const newQuery = { ...route.query };
  161. // 更新 cityid
  162. newQuery.cityid = item.id;
  163. // 检查是否有 select 参数,如果有则删除
  164. if ('select' in newQuery) {
  165. delete newQuery.select;
  166. }
  167. // 使用 router.replace 更新 URL
  168. router.replace({
  169. path: route.path,
  170. query: newQuery
  171. });
  172. }
  173. // import { useCityStore } from '@/store/status'
  174. // // 重置
  175. let panel_reset_fun = () => {
  176. cityId.value = ""
  177. shop_category_id.value = ""
  178. shop_category_pinyin.value = ""
  179. }
  180. // 确定
  181. let panel_sure_fun = () => {
  182. // router.push('/xiangcunshangcheng/nongfuchanpin/index.html')
  183. if (!shop_category_pinyin.value && !cityId.value) {//重置
  184. panelVisible.value = false
  185. router.push(`/xiangcunshangcheng/index.html`)
  186. return
  187. }
  188. if (shop_category_pinyin.value && cityId.value) {//2个都选
  189. panelVisible.value = false
  190. router.push(`/xiangcunshangcheng/${shop_category_pinyin.value}/index.html?cityid=${cityId.value}`)
  191. return
  192. }
  193. if (shop_category_pinyin.value && !cityId.value) {//选择商城首页-但是没选择地区
  194. panelVisible.value = false
  195. router.push(`/xiangcunshangcheng/${shop_category_pinyin.value}/index.html`)
  196. return
  197. }
  198. if (!shop_category_pinyin.value && cityId.value) {//请选择地区province-但是没选商城首页
  199. panelVisible.value = false
  200. router.push(`/xiangcunshangcheng/${shop_category_pinyin_defult.value}/index.html?cityid=${cityId.value}`)
  201. return
  202. }
  203. }
  204. //1.1 获得商城导航
  205. let getShowNav = async () => {
  206. const responseStatus = await requestDataPromise('/web/getWebsiteModelCategory', {
  207. method: 'GET',
  208. query: {
  209. placeid:0,
  210. pid:346,
  211. num:8
  212. },
  213. });
  214. shopNav.value = responseStatus.data
  215. shopNavOnePinyin.value = responseStatus.data[0].aLIas_pinyin
  216. shop_category_pinyin_defult.value = shopNav.value[0].aLIas_pinyin
  217. }
  218. getShowNav();
  219. // 关闭面板
  220. const close_panel_btn_fun = () => {
  221. panelVisible.value = false
  222. }
  223. //获取导航菜单1
  224. async function getNavigation1() {
  225. const mkdata = await requestDataPromise('/web/getWebsiteModelCategory', {
  226. method: 'GET',
  227. query: {
  228. 'pid': 0,
  229. 'num': 20,
  230. 'placeid': 1
  231. },
  232. });
  233. navigation1.value = mkdata.data;
  234. }
  235. getNavigation1();
  236. //深度服务
  237. async function getNavigation3() {
  238. const mkdata = await requestDataPromise('/web/getWebsiteModelCategory', {
  239. method: 'GET',
  240. query: {
  241. 'pid': 0,
  242. 'num': 6,
  243. 'placeid': 33
  244. },
  245. });
  246. navigation3.value = mkdata.data;
  247. }
  248. getNavigation3();
  249. //获取导航菜单4
  250. async function getNavigation4() {
  251. const mkdata = await requestDataPromise('/web/getWebsiteModelCategory', {
  252. method: 'GET',
  253. query: {
  254. 'pid': 0,
  255. 'num': 10,
  256. 'placeid': 23
  257. },
  258. });
  259. navigation4.value = mkdata.data;
  260. }
  261. getNavigation4();
  262. const getLinkPath = (item) => {
  263. close_panel_btn_fun()
  264. let linkPath = ''
  265. if (item.is_url == 1) {
  266. linkPath = `/${item.web_url}`;
  267. } else if (item.children_count == 0) {
  268. //return `/newsList/${item.category_id}?page=1`;
  269. linkPath = `/${item.aLIas_pinyin}/list-1.html`;
  270. } else {
  271. //return `/primaryNavigation/${item.aLIas_pinyin}/`;
  272. linkPath = `/${item.aLIas_pinyin}/index.html`;
  273. }
  274. // router.push(linkPath)
  275. return navigateTo({
  276. path: linkPath,
  277. })
  278. }
  279. onMounted(async () => {
  280. //获得所有的省
  281. try {
  282. const { $webUrl, $CwebUrl } = useNuxtApp();
  283. const response = await fetch($webUrl + '/web/selectWebsiteArea', {
  284. headers: {
  285. 'Content-Type': 'application/json',
  286. 'Userurl': $CwebUrl,
  287. 'Origin': $CwebUrl
  288. }
  289. });
  290. province_arr.value = (await response.json()).data;
  291. } catch (error) {
  292. console.error('获取行政区划数据失败:', error);
  293. }
  294. })
  295. import { watch } from 'vue'
  296. onMounted(() => {
  297. // 监听panelVisible.value的变化
  298. watch(() => panelVisible.value, (newVal) => {
  299. //打开时-清空上1次的选择
  300. if (newVal === true) {
  301. cityId.value = ""
  302. shop_category_id.value = ""
  303. shop_category_pinyin.value = ""
  304. }
  305. })
  306. const delayTimer_hid = ref(null);//延迟器
  307. delayTimer_hid.value = setTimeout(() => {
  308. watch(panelVisible, (newValue, oldValue) => {
  309. // 根据panelVisible的状态执行不同操作
  310. if (newValue) {
  311. document.body.classList.add("body_hid")
  312. } else {
  313. // 面板隐藏时的操作
  314. document.body.classList.remove('body_hid')
  315. }
  316. })
  317. }, 333);
  318. })
  319. // 向左滑动事件相关变量
  320. let touchStartX = 0;
  321. let touchEndX = 0;
  322. let panelMainRef = ref(null);
  323. // 监听向左滑动的最小距离(像素)
  324. const MIN_SWIPE_DISTANCE = 33;
  325. // 向左滑动处理函数
  326. const handleSwipeLeft = () => {
  327. return
  328. // 这里可以执行向左滑动后需要的操作,例如关闭面板
  329. close_panel_btn_fun();
  330. };
  331. // 触摸开始事件
  332. const handleTouchStart = (e) => {
  333. touchStartX = e.touches[0].clientX;
  334. };
  335. // 触摸结束事件
  336. const handleTouchEnd = (e) => {
  337. touchEndX = e.changedTouches[0].clientX;
  338. handleSwipe();
  339. };
  340. // 滑动检测逻辑
  341. const handleSwipe = () => {
  342. const swipeDistance = touchEndX - touchStartX;
  343. // 如果向左滑动的距离大于最小阈值(负值表示向左滑动)
  344. if (swipeDistance < -MIN_SWIPE_DISTANCE) {
  345. handleSwipeLeft();
  346. }
  347. };
  348. onMounted(async () => {
  349. // 获取.panel_main元素并添加触摸事件监听
  350. panelMainRef.value = document.querySelector('.panel_main');
  351. if (panelMainRef.value) {
  352. panelMainRef.value.addEventListener('touchstart', handleTouchStart);
  353. panelMainRef.value.addEventListener('touchend', handleTouchEnd);
  354. }
  355. });
  356. onUnmounted(() => {
  357. // 组件卸载时移除事件监听器,防止内存泄漏
  358. if (panelMainRef.value) {
  359. panelMainRef.value.removeEventListener('touchstart', handleTouchStart);
  360. panelMainRef.value.removeEventListener('touchend', handleTouchEnd);
  361. }
  362. });
  363. </script>
  364. <style lang="less" scoped>
  365. // @import url('@/assets/css/nav.less');
  366. </style>
  367. <style lang="less" scoped>
  368. @media screen and (min-width:801px){/*pc*/
  369. .pc_none{display:none;}
  370. }
  371. @media screen and (max-width:800px){/*ipad_phone*/
  372. .dot1{word-break: keep-all; white-space: nowrap;overflow:hidden;text-overflow:ellipsis; }
  373. .panel_main{
  374. position:fixed;
  375. top:0px;
  376. left:0px;
  377. width:100%;
  378. height:100%;
  379. background:#F6F6F6;
  380. z-index:1999;
  381. overflow:hidden;
  382. }
  383. .panel_head_box{
  384. width:97%;margin:0px auto 4px;
  385. height:50px;border-bottom:1px solid #b8b8b8;
  386. text-align:center;position:relative;
  387. }
  388. .panel_long{
  389. height:100%;
  390. overflow:auto;
  391. }
  392. .panel_head_h4{height:50px;line-height:50px;display:inline-block;
  393. font-size:22px;color:#333;text-align:center;}
  394. .panel_head_btn{float:right;width:22px;height:22px; top:12px;
  395. position:absolute;right:0px;
  396. background:url('../../public/image/guanbi 1.png') no-repeat center center;
  397. background-size:100% 100%;
  398. }
  399. .panel_main_in{width:96%;margin:0px auto;padding-bottom:66px;}
  400. .panel_box{}
  401. .panel_name_box{
  402. width:100%;
  403. height:44px;
  404. }
  405. .panel_name{
  406. float:left;font-weight:bold;
  407. height:44px;
  408. line-height:44px;
  409. font-size:16px;
  410. color:#333;
  411. // padding-left:20px;
  412. }
  413. .panel_a_box{
  414. width:100%;
  415. overflow:hidden;
  416. margin-bottom:10px;
  417. }
  418. .panel_box{
  419. border-top:1px solid #ddd;
  420. }
  421. .panel_box:nth-of-type(1){
  422. border-top:0px;
  423. }
  424. .panel_a_btn{
  425. float:left;
  426. width:23%;margin: 2% 1%;box-sizing:border-box;text-align:center;
  427. height:44px;
  428. line-height:44px;
  429. font-size:12px;
  430. color:#333;
  431. padding:0 4px;background:#F6F6F6;border:solid 1px #ddd;
  432. word-break: keep-all; white-space: nowrap;overflow:hidden;text-overflow:ellipsis;
  433. }
  434. .panel_a_btn_2{
  435. float:left;
  436. width:14%;margin:4px 1.3%;box-sizing:border-box;text-align:center;
  437. height:33px;
  438. line-height:33px;
  439. font-size:14px;
  440. color:#333;
  441. padding:0 8px;background:#F6F6F6;border:solid 1px #ddd;
  442. }
  443. .shop_name_a_only{
  444. background:#A01C0E;border:0;font-weight:bold;
  445. color:#fff;
  446. }
  447. .province_box{
  448. margin-bottom:66px;
  449. }
  450. .panel_foot_btn_box{
  451. width:100%; left:0px;background:#fff;
  452. height:44px; text-align:center;
  453. bottom:0px;position:fixed;
  454. .panel_foot_btn{
  455. padding:0px 11px;
  456. height:33px;
  457. line-height:33px;margin:5px 8px 0px;
  458. font-size:16px;border:solid 1px #ddd;
  459. color:#333;background: #fff;;
  460. border-radius:6px;
  461. display:inline-block;
  462. }
  463. .panel_foot_btn:nth-of-type(2){
  464. color:#fff;background:#A01C0E;
  465. }
  466. }
  467. }
  468. </style>
  469. <style>
  470. @media screen and (min-width:801px){/*pc*/
  471. }
  472. @media screen and (max-width:800px){/*ipad_phone*/
  473. .body_hid{
  474. overflow:hidden;height:100vw!important;
  475. }
  476. }
  477. </style>