first commit

This commit is contained in:
2024-12-10 12:20:05 +08:00
commit f866087c7e
37 changed files with 2080 additions and 0 deletions

43
js/config/index.js Normal file
View File

@@ -0,0 +1,43 @@
// var let
// 定义的新方式 let
let config = {
stage: "dev", // dev test prod
// http://127.0.0.1:8090/app/user/UserInfo
// 基地址 http://127.0.0.1:8090/app
// 短地址 /user/UserInfo
// 基地址都被 ajax封装调用
devUrl: 'http://[240e:362:220c:b200::906]:9940/v1/api',
testUrl: 'http://192.168.31.101:3030/test/api',
prodUrl: 'https://pc.buyusdt.xyz/v1/api',
// 帮助ajax判断应该用哪一个基地址
checkUrl: function () {
switch (this.stage) {
case "dev":
return this.devUrl
break;
case "test":
return this.testUrl
break;
case "prod":
return this.prodUrl
break;
}
},
// 短地址 都被 serve 调用
urlList: {
homeHot: '/home/hot',
homeList: '/home/list',
homeBanner: '/home/banner',
infoList: '/info/list',
tagList: '/tag/list',
tagRecommend: '/tag/recommend',
tagInfo: '/tag/info',
searchHot: '/search/hot',
searchKey: '/search/key',
}
}

49
js/http/index.js Normal file
View File

@@ -0,0 +1,49 @@
class Ajax {
xhr = new XMLHttpRequest()
get(option) {
$("body").mLoading("show")
return new Promise((succ, err) => {
// jquery 是通过 callback 来对异步ajax代码进行封装的
$.ajax({
type: "GET",
// http://192.168.31.101:9940/v1/api + /home/banner
url: config.checkUrl() + option.url,
data: option.data,
success: res => {
$("body").mLoading("hide")
succ( this.stateChange(res) )
},
error: msg => {
err(msg)
}
});
})
}
post(option) {
return new Promise((success, error) => {
})
}
// 对业务状态码进行判断
stateChange(res) {
switch (res.status) {
case 200:
return res.data
break;
case 404:
alert(res.message)
err(this.xhr)
break;
default:
break;
}
}
}

57
js/http/index.js-old Normal file
View File

@@ -0,0 +1,57 @@
class Ajax {
xhr = new XMLHttpRequest()
get(option) {
return new Promise((success, error) => {
var params = ""
for (const key in option.data) {
params += `&${key}=${option.data[key]}`
}
params = params.replace("&", "?")
// option.url == /home/hot?id=1
this.xhr.open("GET", `${config.checkUrl()}${option.url}${params}`)
this.xhr.send()
this.stateChange(success, error)
})
}
post(option) {
return new Promise((success, error) => {
this.xhr.open("POST", option.url)
this.xhr.setRequestHeader("Content-Type", "application/json")
// post 参数在请求体(body)中发送
this.xhr.send(JSON.stringify(option.data))
this.stateChange(success, error)
})
}
stateChange(suc, err) {
this.xhr.onreadystatechange = () => {
if (this.xhr.readyState == 4) {
if (this.xhr.status == 200) {
let res = JSON.parse(this.xhr.response)
switch (res.status) {
case 200:
suc(res.data)
break;
case 404:
alert(res.message)
err(this.xhr)
break;
default:
break;
}
suc()
} else {
err(this.xhr)
}
}
}
}
}

2
js/lib/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

14
js/lib/swiper-bundle.min.js vendored Normal file

File diff suppressed because one or more lines are too long

136
js/page/domestic.js Normal file
View File

@@ -0,0 +1,136 @@
class Domestic {
mySwiper = null;
tagList = [];
index = localStorage.getItem("index") || 0;
// 原生js dom操作全部忘记都没关系
// diff 虚拟dom 映射(局部渲染) 到真实dom
constructor() {
header(
`<div class="header_title flex1 ellipsis">分类</div>`,
``,
``
)
footer()
this.getTagServeData()
}
async getTagServeData() {
let self = this;
this.tagList = await tagServe.tagList()
console.log(this.tagList);
eachHtml(
".type_list",
this.tagList,
(v, i) => `<li class="${i == this.index ? 'active' : ''}">${v.title}</li>`
)
$(".swiper-wrapper").append(
this.tagList.map(v => {
return `<div class="swiper-slide recommend-model default-model">
<ul class="flex list p15 js"></ul>
</div>`
})
)
$(".type_list li").click(function () {
$(this).addClass("active").siblings().removeClass("active")
self.mySwiper.slideTo($(this).index())
})
this.initSwiper()
if (this.index == 0) {
await this.getTagInfoData()
} else {
console.log("this.index: ", this.index);
this.mySwiper.slideTo(this.index)
}
this.onIScroll()
}
// 第一次调用 点击按钮(滑动轮播图) click
// 第二次调用 滚动加载 scroll
async getTagInfoData(type = "click") {
let loadData = async () => {
let { totalPage, list } = await tagServe.tagInfo({
url: this.tagList[this.index].url,
page: this.tagList[this.index].page
})
this.tagList[this.index].totalPage = totalPage
this.tagList[this.index].content = [
...this.tagList[this.index].content,
...list
]
// 向不同的 ul 中插入不同的内容
eachHtml(
// $(".swiper-slide ul") 返回的是数组
// eq 用来获取数组+下标的
// [1,2,3][0] 取到的虚拟dom这种无法使用jquery方法
$(".swiper-slide ul").eq(this.index),
list,
(v) => item(v)
)
//this.onIScroll()
}
if (type == "click") {
if (this.tagList[this.index].content.length == 0) {
// 加载请求
loadData()
}
} else {
// 加载请求
loadData()
}
}
initSwiper() {
let self = this;
this.mySwiper = new Swiper('.type_list_content', {
on: {
slideChange: async function () {
self.index = this.activeIndex
localStorage.setItem("index", self.index)
await self.getTagInfoData()
$(".type_list li").eq(this.activeIndex).addClass("active").siblings().removeClass("active")
},
},
})
}
onIScroll() {
let self = this;
// $(window)
$(".swiper-slide").scroll(async function () {
let scrollTop = $(this).scrollTop();
let ulHeight = $(this).find("ul").height()
// 可视区域高度 529
let windowHeight = $(this).height();
console.log("scrollTop: ", scrollTop);
console.log("windowHeight: ", windowHeight);
console.log("ulHeight: ", ulHeight);
if (Math.round(scrollTop + windowHeight - 15) >= parseInt(ulHeight)) {
console.log("到底部");
self.tagList[self.index].page += 1
if (self.tagList[self.index].page <= self.tagList[self.index].totalPage) {
await self.getTagInfoData("scroll")
}
}
});
}
}
new Domestic

7
js/page/hot.js Normal file
View File

@@ -0,0 +1,7 @@
class Hot {
constructor() {
}
}
new Hot

79
js/page/index.js Normal file
View File

@@ -0,0 +1,79 @@
class Index {
constructor() {
header(`
<div class="search flex1 flex ais">
<i class="iconfont icon-sousuo-m"></i>
<p>开启精彩搜索..</p>
</div>
`, '', '')
// 虚拟domjs对象虚拟dom的数组[{},{}]
// 数组不是原生数组是jq定义的数组
// console.log($("body")[0].innerHTML = ``);
// console.log($("body").html(`a`));
footer()
this.getHomeBannerData()
this.getHomeHotData()
this.getHomeListData()
this.getTagRecommendData()
this.event()
}
event() {
$(".search").click(() => {
location.href = "./search.html"
})
}
async getTagRecommendData() {
eachHtml(
".recommend-tag",
await tagServe.tagRecommend(),
(v) => `
<li>
<a class="icon" href="./tagListInfo.html?url=${v.url}&title=${v.title}">${v.title.substr(0,1)}</a>
<a class="title" href="./tagListInfo.html?url=${v.url}&title=${v.title}">${v.title}</a>
</li>
`
)
}
async getHomeBannerData() {
eachHtml(
".swiper-wrapper",
await homeServe.homeBanner(),
(v) => `<div class="swiper-slide"><img src="${v.src}" alt=""></div>`
)
this.initSwiper()
}
async getHomeListData() {
eachHtml(
".default-model ul",
await homeServe.homeList(),
(v) => item(v)
)
}
async getHomeHotData() {
eachHtml(
".recommend-horizontally ul",
await homeServe.homeHot(),
(v) => item(v)
)
}
initSwiper() {
new Swiper('.banner', {
loop: true,
pagination: {
el: '.swiper-pagination',
},
})
}
}
new Index

97
js/page/info.js Normal file
View File

@@ -0,0 +1,97 @@
class Info {
title = "";
defaultArr = []
allArr = [];
like = JSON.parse(localStorage.getItem("like")) || [];
constructor() {
this.init()
}
async init() {
await this.getInfoListData()
header(
`<div class="header_title flex1 ellipsis">${this.title}</div>`,
`
<div class="ilist">
<i class="iconfont icon-wujiaoxing"></i>
<i class="iconfont icon-fenxiang"></i>
</div>
`
)
this.event()
}
async getInfoListData() {
let { title, src_list, recommend } = await infoServe.infoList({
id: query("id")
})
this.title = title
this.defaultArr = src_list.splice(0, 2)
this.allArr = src_list
eachHtml(
".info_img_list .img_list",
this.defaultArr,
(v) => `<img src="${v}" alt="">`
)
eachHtml(
".default-model ul",
recommend,
(v) => item(v)
)
}
event() {
this.like.filter(v => v.id == query("id")).length != 0
? $(".icon-wujiaoxing").addClass("icon-wujiaoxing1")
: null
$(".icon-fenxiang").click(async () => {
await navigator.clipboard.writeText(`
我这有个好看的,快来看看 ${this.title}
${location.href}
`)
alert("内容已复制")
})
$(".icon-wujiaoxing").click(() => {
// 如果有icon-wujiaoxing1表示收藏过了
if ($(".icon-wujiaoxing").hasClass("icon-wujiaoxing1")) {
this.like = this.like.filter(v => v.id != query("id"))
// 没有 icon-wujiaoxing1表示未收藏过了
} else {
this.like.push({
"id": query("id"),
"thumbnail": this.defaultArr[0],
"title": this.title,
"time": query("time"),
"view": "42"
})
}
localStorage.setItem("like", JSON.stringify(this.like))
$(".icon-wujiaoxing").toggleClass("icon-wujiaoxing1")
})
$(".view_all").click(() => {
$(".img_list").css({ height: 'auto' })
eachHtml(
".info_img_list .img_list",
this.allArr,
(v) => `<img src="${v}" alt="">`
)
$(".view_all").css({ display: 'none' })
})
}
}
new Info

6
js/page/me.js Normal file
View File

@@ -0,0 +1,6 @@
class Me {
constructor() {
}
}
new Me

76
js/page/search.js Normal file
View File

@@ -0,0 +1,76 @@
class Search {
page = 1;
totalPage = 0;
keyword = "";
constructor() {
header(
`<input class="flex1" type="text" placeholder="输入关键字">`,
`<div class="button">搜索</div>`,
`<i class="iconfont icon-fanhui"></i>`
)
this.getSearchHotData()
this.enevt()
}
async getSearchHotData() {
let { hotKeyword, recommend } = await searchServe.searchHot()
eachHtml(
'.search_list ul',
hotKeyword,
(v) => `<li><a>${v}</a></li>`
)
$(".search_list ul li").click(function () {
$(".header input").val($(this).text())
$(".header .button").click()
})
eachHtml(
'.search_recommend',
recommend,
(v) => item(v, 2)
)
}
async getSearchKeyData() {
let { totalPage, list } = await searchServe.searchKey({
keyword: this.keyword,
page: this.page
})
this.totalPage = totalPage
eachHtml(
'.have-search ul',
list,
(v) => item(v)
)
$(".no-search").hide()
$(".have-search").show()
}
enevt() {
$(".header .button").click(async () => {
if ($(".header input").val().length != 0) {
this.keyword = $(".header input").val()
await this.getSearchKeyData()
}
})
$(".header input").on("input", function () {
if ($(".header input").val().length == 0) {
$(".no-search").show()
$(".have-search").hide()
}
});
}
}
new Search

6
js/page/tagListInfo.js Normal file
View File

@@ -0,0 +1,6 @@
class TagListInfo {
constructor() {
}
}
new TagListInfo

35
js/serve/home.js Normal file
View File

@@ -0,0 +1,35 @@
class HomeServe {
// data 是接口请求的参数,默认为空对象,表示这个接口不需要参数
async homeHot (data = {}) {
let http = new Ajax()
// suc的返回值ajax请求到的后端给我们的数据
return await http.get({
url: config.urlList.homeHot,
// data: data key 和 value 名字一样的时候,可以直接只写一个
data
})
}
async homeBanner (data = {}) {
let http = new Ajax()
// suc的返回值ajax请求到的后端给我们的数据
return await http.get({
url: config.urlList.homeBanner,
// data: data key 和 value 名字一样的时候,可以直接只写一个
data
})
}
async homeList (data = {}) {
let http = new Ajax()
// suc的返回值ajax请求到的后端给我们的数据
return await http.get({
url: config.urlList.homeList,
// data: data key 和 value 名字一样的时候,可以直接只写一个
data
})
}
}
let homeServe = new HomeServe

14
js/serve/info.js Normal file
View File

@@ -0,0 +1,14 @@
class InfoServe {
// data 是接口请求的参数,默认为空对象,表示这个接口不需要参数
async infoList (data = {}) {
let http = new Ajax()
// suc的返回值ajax请求到的后端给我们的数据
return await http.get({
url: config.urlList.infoList,
// data: data key 和 value 名字一样的时候,可以直接只写一个
data
})
}
}
let infoServe = new InfoServe

28
js/serve/search.js Normal file
View File

@@ -0,0 +1,28 @@
class SearchServe {
// data 是接口请求的参数,默认为空对象,表示这个接口不需要参数
async searchHot (data = {}) {
let http = new Ajax()
// suc的返回值ajax请求到的后端给我们的数据
return await http.get({
url: config.urlList.searchHot,
// data: data key 和 value 名字一样的时候,可以直接只写一个
data
})
}
async searchKey (data = {}) {
let http = new Ajax()
// suc的返回值ajax请求到的后端给我们的数据
return await http.get({
url: config.urlList.searchKey,
// data: data key 和 value 名字一样的时候,可以直接只写一个
data
})
}
}
let searchServe = new SearchServe

43
js/serve/tag.js Normal file
View File

@@ -0,0 +1,43 @@
class TagServe {
// 简化我们的ajax请求过程
// 可以实现对接口返回数据的修改
// data 是接口请求的参数,默认为空对象,表示这个接口不需要参数
async tagList (data = {}) {
let http = new Ajax()
// suc的返回值ajax请求到的后端给我们的数据
let res = await http.get({
url: config.urlList.tagList,
// data: data key 和 value 名字一样的时候,可以直接只写一个
data
})
res.forEach(v => {
v.content = [];
v.totalPage = 0;
v.page = 1;
});
return res;
}
async tagInfo (data = {}) {
let http = new Ajax()
// suc的返回值ajax请求到的后端给我们的数据
return await http.get({
url: config.urlList.tagInfo,
// data: data key 和 value 名字一样的时候,可以直接只写一个
data
})
}
async tagRecommend (data = {}) {
let http = new Ajax()
// suc的返回值ajax请求到的后端给我们的数据
return await http.get({
url: config.urlList.tagRecommend,
// data: data key 和 value 名字一样的时候,可以直接只写一个
data
})
}
}
let tagServe = new TagServe

77
js/utils/index.js Normal file
View File

@@ -0,0 +1,77 @@
class Utils {
header(content, action, back = `<i class="iconfont icon-fanhui"></i>`) {
$("body").prepend(`
<div class="header fixed flex ais flex1 border-box p15">
${back}
${content}
${action}
</div>
`)
$(".icon-fanhui").click(() => history.back())
}
eachHtml(dom, data, callback) {
$(dom).append(
data.map((v,i) => callback(v,i))
)
}
item(v, theme = 1) {
return `
<li class="${theme == 2 ? 'item-theme-horizontally' : ''}">
<a href="./info.html?id=${v.id}&time=${v.time}">
<img src="${v.thumbnail}" alt="">
<div class="r">
<div class="text ellipsis">${v.title}</div>
<div class="desc flex ais js">
<div class="time">${v.time}</div>
<div class="view flex ais">
<i class="iconfont icon-yanjing"></i>
<span>${v.view}</span>
</div>
</div>
</div>
</a>
</li>
`
}
footer() {
// ajax 接口返回的底部导航数据
let arr = [
{ icon: 'icon-shouye', title: '首页', href: 'index.html' },
{ icon: 'icon-changchenglogo', title: '分类', href: 'domestic.html' },
{ icon: 'icon-hot', title: '热门', href: 'hot.html' },
{ icon: 'icon-wo', title: '我的', href: 'me.html' },
]
$("body").append(`
<ul class="footer fixed flex ja ais">
${arr.map(v => {
return `
<li class="${location.pathname.includes(v.href) ? 'active' : ''}">
<a href="${v.href}">
<i class="iconfont ${v.icon}"></i>
<p>${v.title}</p>
</a>
</li>`
})}
</ul>
`)
}
query(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if (r != null) return decodeURIComponent(r[2]); return null;
}
}
let u = new Utils
let util = u,
{
header, eachHtml, item,
footer, query
}
= u

10
js/utils/rem.js Normal file
View File

@@ -0,0 +1,10 @@
(function (w, d) {
function setSize() {
var screenWidth = d.documentElement.clientWidth;
var currentFontSize = (screenWidth * 100) / 750;
d.documentElement.style.fontSize = currentFontSize + "px";
}
w.addEventListener("resize", setSize);
w.addEventListener("pageShow", setSize);
w.addEventListener("DOMContentLoaded", setSize);
})(window, document);