├── .babelrc ├── .browserslistrc ├── .eslintrc.js ├── .gitignore ├── LICENSE ├── README.md ├── babel.config.js ├── package.json ├── public ├── favicon.ico ├── index.html └── robots.txt ├── src ├── App.vue ├── api │ ├── boxApi.js │ ├── commonApi.js │ └── userApi.js ├── assets │ ├── css │ │ ├── global.scss │ │ └── reset.scss │ ├── iconfont │ │ ├── iconfont.css │ │ ├── iconfont.eot │ │ ├── iconfont.svg │ │ ├── iconfont.ttf │ │ ├── iconfont.woff │ │ └── iconfont.woff2 │ ├── img │ │ ├── bg.gif │ │ └── bg.png │ └── js │ │ └── bjxt.js ├── components │ ├── common │ │ ├── Add.vue │ │ ├── BackgroundEffect.vue │ │ ├── LeaveMsg.vue │ │ ├── Music.vue │ │ ├── Notice.vue │ │ ├── People.vue │ │ ├── Sort.vue │ │ ├── ToHot.vue │ │ ├── ToMall.vue │ │ ├── ToNav.vue │ │ └── Weather.vue │ ├── dialog │ │ ├── AddBoxDialog.vue │ │ ├── AddListDialog.vue │ │ ├── AddSearchSiteDialog.vue │ │ ├── ImageDialog.vue │ │ ├── LeaveMsgDialog.vue │ │ ├── MsgReplyDialog.vue │ │ ├── MusicSettingDialog.vue │ │ ├── NoticeDialog.vue │ │ ├── UpdateBoxDialog.vue │ │ ├── UpdateListDialog.vue │ │ ├── UpdateSearchSiteDialog.vue │ │ ├── ViewMsgDialog.vue │ │ ├── WeatherDialog.vue │ │ └── WechatDialog.vue │ ├── drawer │ │ └── AddDrawer.vue │ ├── item │ │ ├── MsgItem.vue │ │ └── NavItem.vue │ ├── step │ │ └── FindPassStep.vue │ └── user │ │ ├── Bottom.vue │ │ ├── Left.vue │ │ └── Top.vue ├── config │ ├── TransformData.js │ ├── code.js │ ├── config.js │ ├── events.js │ ├── getInfo.js │ ├── guide.json │ ├── http.js │ ├── keys.js │ ├── strings.js │ └── updateNotes.json ├── element │ └── index.js ├── main.js ├── router │ └── index.js ├── store │ ├── index.js │ ├── mutations.js │ └── state.js ├── util │ ├── isMobile.js │ └── utils.js └── views │ ├── Index.vue │ ├── Search.vue │ ├── TokenAdd.vue │ ├── User.vue │ ├── index │ ├── Footer.vue │ ├── Header.vue │ ├── Nav.vue │ ├── RightBar.vue │ └── Search.vue │ └── user │ ├── AboutUs.vue │ ├── BoxConfig.vue │ ├── ExportConfig.vue │ ├── Home.vue │ ├── ImportConfig.vue │ ├── ListConfig.vue │ ├── ModifyPass.vue │ ├── MsgConfig.vue │ ├── NoticeConfig.vue │ ├── Profile.vue │ ├── SearchSiteConfig.vue │ ├── SiteConfig.vue │ ├── UpdateNote.vue │ └── UserLogin.vue └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | [ 4 | "component", 5 | { 6 | "libraryName": "element-ui", 7 | "styleLibraryName": "theme-chalk" 8 | } 9 | ] 10 | ] 11 | } -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true 5 | }, 6 | 'extends': [ 7 | 'plugin:vue/essential', 8 | 'eslint:recommended' 9 | ], 10 | parserOptions: { 11 | parser: 'babel-eslint' 12 | }, 13 | rules: { 14 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 15 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 优聚集 2 | 3 | 2020年初,疫情肆虐,想着以后的规划,结果是毫无规划,可能我就是随波逐流、活在当下的人。 4 | 5 | 6 | 7 | 不管怎么说,我也希望以后能自由职业且能不饿肚子,为此,为了锻炼技能,写了优聚集这个前后端分离的项目。 8 | 9 | 10 | 11 | 这是第一次写较大规模的Vue.js 应用 12 | 13 | 这也是第一次写较大规模的SpringBoot应用 14 | 15 | 16 | 17 | 第一次写,肯定就是巨难看和维护,这点我有自知之明,但是我希望你们不要说出来。我自己知道就行。所以,于2021年我完全从零开始重构了优聚集,前端虽也是Vue.js,但是也是完全重写了。后端用golang重构。不得不说,golang没有像springboot这类似的大统一框架,对于某些方面来说也是好事,我可以完全决定我的后台应用怎么架构。而不是被springboot规定死了:你就该在这个目录写这个东西… 18 | 19 | 20 | 21 | ### 仓库 22 | 23 | 前端仓库(Vue.js):[https://github.com/Xwudao/ujuji_frontend](https://github.com/Xwudao/ujuji_frontend) 24 | 25 | 后端仓库(SpringBoot):[https://github.com/Xwudao/ujuji_backend](https://github.com/Xwudao/ujuji_backend) 26 | 27 | 28 | 29 | ### 声明 30 | 31 | 1、 32 | 33 | 尽管我已经仔细检查过代码,但是不可避免的可能代码中依旧有一些我个人的私密信息,尤其是诸如邮箱密码之类的,如果被发现了,那么请告知我,或者最起码请不要用它干一些危险的事情,谢谢合作。 34 | 35 | 2、 36 | 37 | 因为本套代码之初并不是为了开源而写的,所以对于一些测试中的敏感信息我都是直接写死在代码中的,所以如果您发现了一些私密信息请告知我。 38 | 39 | 40 | 41 | 3、 42 | 43 | 本套代码是基于Vue2.js 44 | 45 | 这套代码和现在的优聚集 [https://ujuji.com/](https://ujuji.com/) 有很大区别,因为现在的优聚集网站时是我完全在2021年通过golang重构了的。**所以当您发现这和优聚集https://ujuji.com/ 差别很大时,很正常,因为现有优聚集是重构之后的版本。** 46 | 47 | 48 | 49 | 4、 50 | 51 | 如果您想自己部署优聚集前后端项目,最起码得有以下知识点: 52 | 53 | - Node.js 54 | - Vue.js 55 | - Javascript 56 | 57 | 58 | 59 | ### 构建 60 | 61 | 1、修改配置文件`src\config\config.js` 62 | 63 | 您最起码得修改这一个配置我呢见,其余的,我也忘了,有一些背景图片,赞赏二维码应该是写死在代码里面的,可能需要你找找… 64 | 65 | - 修改后台服务器地址: 66 | 67 | ```javascript 68 | let url; 69 | if (process.env.NODE_ENV === 'production') { 70 | url = 'https://api.ujuji.com' 71 | } else { 72 | url = 'http://localhost:4037' 73 | } 74 | ``` 75 | 76 | 上面的http://localhost:4037 是本地开发环境的后台服务器地址,https://api.ujuji.com 是线上后台服务器地址 77 | 78 | 79 | 2、当基本配置修改完后,就可以构建了: 80 | 81 | 执行(需要Nodejs环境) 82 | 83 | ```bash 84 | npm i 85 | ``` 86 | 87 | 构建: 88 | 89 | ``` 90 | npm run build 91 | ``` 92 | 93 | 94 | 95 | 成功后,会输出: 96 | 97 | ```ini 98 | File Size Gzipped 99 | 100 | dist\js\chunk-vendors.7dea26e0.js 587.00 KiB 160.49 KiB 101 | dist\js\chunk-d225f4dc.edb1e5e0.js 457.38 KiB 139.79 KiB 102 | dist\js\app.3793e2c6.js 54.83 KiB 16.93 KiB 103 | dist\js\chunk-3a3be80e.e9fbef86.js 17.79 KiB 5.94 KiB 104 | dist\js\chunk-49d141fb.a96c2f31.js 16.15 KiB 5.63 KiB 105 | dist\js\chunk-2304eda0.2f1c8d34.js 14.27 KiB 3.98 KiB 106 | dist\js\chunk-b851b192.f72d5b6f.js 14.02 KiB 3.49 KiB 107 | dist\js\chunk-05d7e486.666513f8.js 13.73 KiB 4.69 KiB 108 | dist\js\chunk-10c0c0ac.f3d8a8a1.js 12.26 KiB 3.45 KiB 109 | dist\js\chunk-1d8d5dbe.18b0d22f.js 10.31 KiB 3.08 KiB 110 | dist\js\chunk-4147566f.96f48fad.js 7.40 KiB 2.48 KiB 111 | dist\js\chunk-71414ebd.a8aa982a.js 7.28 KiB 2.29 KiB 112 | dist\js\chunk-18609744.b586d9ff.js 6.08 KiB 1.96 KiB 113 | dist\js\chunk-22de37c4.3677e01d.js 5.84 KiB 2.13 KiB 114 | dist\js\chunk-772f45f6.89282213.js 5.68 KiB 2.46 KiB 115 | dist\js\chunk-2e227146.4c3af2c2.js 4.86 KiB 2.15 KiB 116 | dist\js\chunk-2d2134f8.d57a94a9.js 2.59 KiB 1.23 KiB 117 | dist\js\chunk-11fbe2c4.f726b5da.js 2.25 KiB 1.09 KiB 118 | dist\js\chunk-2d0bff6a.0d05008e.js 1.97 KiB 0.99 KiB 119 | dist\js\chunk-350dbcac.65ad8f0c.js 1.80 KiB 0.91 KiB 120 | dist\js\chunk-2fd8105c.e4c1219d.js 1.56 KiB 0.73 KiB 121 | dist\css\chunk-vendors.b87d1f59.css 208.08 KiB 33.54 KiB 122 | dist\css\app.ea1689dd.css 16.43 KiB 8.13 KiB 123 | dist\css\chunk-2fd8105c.6e27bbcb.css 2.54 KiB 0.86 KiB 124 | dist\css\chunk-d225f4dc.b5e4bbcb.css 1.25 KiB 0.42 KiB 125 | dist\css\chunk-11fbe2c4.bd7e1ba0.css 0.69 KiB 0.31 KiB 126 | dist\css\chunk-1d8d5dbe.3a0848fc.css 0.51 KiB 0.25 KiB 127 | dist\css\chunk-4147566f.eb28eeef.css 0.48 KiB 0.24 KiB 128 | dist\css\chunk-05d7e486.1ae9b438.css 0.40 KiB 0.21 KiB 129 | dist\css\chunk-350dbcac.a836ecb7.css 0.34 KiB 0.19 KiB 130 | dist\css\chunk-71414ebd.530fb09f.css 0.28 KiB 0.17 KiB 131 | dist\css\chunk-22de37c4.ec67429c.css 0.25 KiB 0.16 KiB 132 | dist\css\chunk-49d141fb.daa62c3a.css 0.25 KiB 0.14 KiB 133 | dist\css\chunk-3a3be80e.8781878b.css 0.19 KiB 0.13 KiB 134 | dist\css\chunk-2e227146.23590e22.css 0.13 KiB 0.12 KiB 135 | dist\css\chunk-18609744.961bc328.css 0.12 KiB 0.10 KiB 136 | dist\css\chunk-2304eda0.27c6ebd0.css 0.12 KiB 0.11 KiB 137 | dist\css\chunk-b851b192.5fa2fcc7.css 0.12 KiB 0.11 KiB 138 | dist\css\chunk-10c0c0ac.d98e47c9.css 0.10 KiB 0.10 KiB 139 | dist\css\chunk-772f45f6.0e433876.css 0.00 KiB 0.02 KiB 140 | 141 | Images and other types of assets omitted. 142 | ``` 143 | 144 | 构建出的产物是: 145 | 146 | `dist\` 147 | 148 | 简单来说把整个dist目录里面的内容放到静态服务器上就行 149 | 150 | 151 | 152 | **** 153 | 154 | 155 | 156 | 好了,基本配置的就完了,**懂Node.js会Vue.js不用我说都知道怎么弄,不会的,我写再多也是一脸懵** 157 | 158 | 159 | 160 | 如果有哪位大神愿意出一个详细的教程,有视频更好,欢迎@我 161 | 162 | 163 | 164 | ### 感谢 165 | 166 | 167 | 168 | 感谢Jetbrains 这家伟大的IDE开发公司,他们的全家桶极其好用 169 | 170 | [https://jetbrains.com/](https://jetbrains.com/) 171 | 172 | 173 | 174 | ### 协议 175 | 176 | 使用本代码请保留前端界面到 https://ujuji.com 的链接 177 | 178 | Apache License 2.0 179 | 180 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ujuji_navigation", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "awe-dnd": "^0.3.4", 12 | "axios": "^0.19.2", 13 | "bookmark-file-parser": "^0.12.6", 14 | "clipboard": "^2.0.6", 15 | "core-js": "^3.6.4", 16 | "element-ui": "^2.13.2", 17 | "vue": "^2.6.11", 18 | "vue-router": "^3.1.6", 19 | "vuex": "^3.1.3", 20 | "xlsx-oc": "^1.0.2" 21 | }, 22 | "devDependencies": { 23 | "@vue/cli-plugin-babel": "^4.3.0", 24 | "@vue/cli-plugin-eslint": "^4.3.0", 25 | "@vue/cli-service": "^4.3.0", 26 | "babel-eslint": "^10.1.0", 27 | "babel-plugin-component": "^1.1.1", 28 | "eslint": "^7.6.0", 29 | "eslint-plugin-vue": "^6.2.2", 30 | "node-sass": "^4.12.0", 31 | "sass-loader": "^8.0.2", 32 | "vue-template-compiler": "^2.6.11" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Xwudao/ujuji_frontend/5e0904054e32ef4cc34641520b269a9d2fc02ec2/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 20 | 21 | 优质网站 | 优聚集 22 | 23 | 24 | 27 |
28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 30 | 31 | 53 | -------------------------------------------------------------------------------- /src/api/boxApi.js: -------------------------------------------------------------------------------- 1 | import http from '../config/http'; 2 | 3 | export const reqBoxData = (userId) => { 4 | return http.get('/user/box/user/' + userId) 5 | } 6 | export const reqBoxesByToken = (token) => { 7 | return http.get(`/public/allBoxes/token/${token}`) 8 | } 9 | 10 | export const reqAddLink = (token, data) => { 11 | return http.post(`/public/token/${token}`, {...data}) 12 | } 13 | -------------------------------------------------------------------------------- /src/api/commonApi.js: -------------------------------------------------------------------------------- 1 | import http from '../config/http' 2 | 3 | export const reqTQData = (city = '') => { 4 | return http.get('/public/weather?city='+city) 5 | } 6 | -------------------------------------------------------------------------------- /src/api/userApi.js: -------------------------------------------------------------------------------- 1 | import http from '../config/http'; 2 | 3 | export const reqImportBox = (data) => { 4 | return http.post('/user/box/import', {...data}) 5 | } 6 | export const reqUserInfo = () => { 7 | return http.get('/auth/info') 8 | } 9 | 10 | export const reqGenerateToken = () => { 11 | return http.post('/auth/token') 12 | } 13 | -------------------------------------------------------------------------------- /src/assets/css/global.scss: -------------------------------------------------------------------------------- 1 | html, body, #app { 2 | width: 100%; 3 | height: 100%; 4 | } 5 | 6 | .search { 7 | .search-input { 8 | input { 9 | background-color: rgba(0, 0, 0, .2) !important; 10 | border-top-left-radius: 25px; 11 | border-bottom-left-radius: 25px; 12 | padding: 0 1.5rem; 13 | border-width: 0; 14 | color: white; 15 | transition: all .1s; 16 | 17 | &:hover { 18 | transition: all .1s; 19 | background-color: rgba(0, 0, 0, .5) !important; 20 | } 21 | } 22 | 23 | //.el-input-group__append { 24 | // background: transparent; 25 | // border: none; 26 | // border-width: 0 !important; 27 | //} 28 | .el-input-group__append { 29 | background-color: rgba(0, 0, 0, .2); 30 | color: white; 31 | font-size: 18px; 32 | border-top-right-radius: 25px; 33 | border-bottom-right-radius: 25px; 34 | border-width: 0; 35 | cursor: pointer; 36 | } 37 | } 38 | 39 | } 40 | 41 | .el-drawer, .el-drawer__header > :first-child { 42 | &:focus { 43 | outline: none !important; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/assets/css/reset.scss: -------------------------------------------------------------------------------- 1 | body, div, li, ul, ol { 2 | font-family: Arial, sans-serif; 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | body { 8 | //background-color: #eeeeee; 9 | font-size: 16px; 10 | } -------------------------------------------------------------------------------- /src/assets/iconfont/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Xwudao/ujuji_frontend/5e0904054e32ef4cc34641520b269a9d2fc02ec2/src/assets/iconfont/iconfont.eot -------------------------------------------------------------------------------- /src/assets/iconfont/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Xwudao/ujuji_frontend/5e0904054e32ef4cc34641520b269a9d2fc02ec2/src/assets/iconfont/iconfont.ttf -------------------------------------------------------------------------------- /src/assets/iconfont/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Xwudao/ujuji_frontend/5e0904054e32ef4cc34641520b269a9d2fc02ec2/src/assets/iconfont/iconfont.woff -------------------------------------------------------------------------------- /src/assets/iconfont/iconfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Xwudao/ujuji_frontend/5e0904054e32ef4cc34641520b269a9d2fc02ec2/src/assets/iconfont/iconfont.woff2 -------------------------------------------------------------------------------- /src/assets/img/bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Xwudao/ujuji_frontend/5e0904054e32ef4cc34641520b269a9d2fc02ec2/src/assets/img/bg.gif -------------------------------------------------------------------------------- /src/assets/img/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Xwudao/ujuji_frontend/5e0904054e32ef4cc34641520b269a9d2fc02ec2/src/assets/img/bg.png -------------------------------------------------------------------------------- /src/assets/js/bjxt.js: -------------------------------------------------------------------------------- 1 | !function () { 2 | //封装方法,压缩之后减少文件大小 3 | function get_attribute(node, attr, default_value) { 4 | return node.getAttribute(attr) || default_value; 5 | } 6 | 7 | //封装方法,压缩之后减少文件大小 8 | function get_by_tagname(name) { 9 | return document.getElementsByTagName(name); 10 | } 11 | 12 | //获取配置参数 13 | function get_config_option() { 14 | var scripts = get_by_tagname("script"), 15 | script_len = scripts.length, 16 | script = scripts[script_len - 1]; //当前加载的script 17 | return { 18 | l: script_len, //长度,用于生成id用 19 | z: get_attribute(script, "zIndex", -1), //z-index 20 | o: get_attribute(script, "opacity", 0.5), //opacity 21 | c: get_attribute(script, "color", "255,255,255"), //color 22 | n: get_attribute(script, "count", 99) //count 23 | }; 24 | } 25 | 26 | //设置canvas的高宽 27 | function set_canvas_size() { 28 | canvas_width = the_canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth, 29 | canvas_height = the_canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight; 30 | } 31 | 32 | //绘制过程 33 | function draw_canvas() { 34 | context.clearRect(0, 0, canvas_width, canvas_height); 35 | //随机的线条和当前位置联合数组 36 | var all_array = [current_point].concat(random_lines); 37 | var e, i, d, x_dist, y_dist, dist; //临时节点 38 | //遍历处理每一个点 39 | random_lines.forEach(function (r) { 40 | r.x += r.xa, 41 | r.y += r.ya, //移动 42 | r.xa *= r.x > canvas_width || r.x < 0 ? -1 : 1, 43 | r.ya *= r.y > canvas_height || r.y < 0 ? -1 : 1, //碰到边界,反向反弹 44 | context.fillRect(r.x - 0.5, r.y - 0.5, 1, 1); //绘制一个宽高为1的点 45 | for (i = 0; i < all_array.length; i++) { 46 | e = all_array[i]; 47 | //不是当前点 48 | if (r !== e && null !== e.x && null !== e.y) { 49 | x_dist = r.x - e.x, //x轴距离 l 50 | y_dist = r.y - e.y, //y轴距离 n 51 | dist = x_dist * x_dist + y_dist * y_dist; //总距离, m 52 | dist < e.max && (e === current_point && dist >= e.max / 2 && (r.x -= 0.03 * x_dist, r.y -= 0.03 * y_dist), //靠近的时候加速 53 | d = (e.max - dist) / e.max, 54 | context.beginPath(), 55 | context.lineWidth = d / 2, 56 | context.strokeStyle = "rgba(" + config.c + "," + (d + 0.2) + ")", 57 | context.moveTo(r.x, r.y), 58 | context.lineTo(e.x, e.y), 59 | context.stroke()); 60 | } 61 | } 62 | all_array.splice(all_array.indexOf(r), 1); 63 | 64 | }), frame_func(draw_canvas); 65 | } 66 | 67 | //创建画布,并添加到body中 68 | var the_canvas = document.createElement("canvas"), //画布 69 | config = get_config_option(), //配置 70 | canvas_id = "c_n" + config.l, //canvas id 71 | context = the_canvas.getContext("2d"), canvas_width, canvas_height, 72 | frame_func = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (func) { 73 | window.setTimeout(func, 1000 / 45); 74 | }, random = Math.random, 75 | current_point = { 76 | x: null, //当前鼠标x 77 | y: null, //当前鼠标y 78 | max: 20000 79 | }; 80 | the_canvas.id = canvas_id; 81 | the_canvas.style.cssText = "position:fixed;top:0;left:0;z-index:" + config.z + ";opacity:" + config.o; 82 | get_by_tagname("body")[0].appendChild(the_canvas); 83 | //初始化画布大小 84 | 85 | set_canvas_size(), window.onresize = set_canvas_size; 86 | //当时鼠标位置存储,离开的时候,释放当前位置信息 87 | window.onmousemove = function (e) { 88 | e = e || window.event, current_point.x = e.clientX, current_point.y = e.clientY; 89 | }, window.onmouseout = function () { 90 | current_point.x = null, current_point.y = null; 91 | }; 92 | //随机生成config.n条线位置信息 93 | for (var random_lines = [], i = 0; config.n > i; i++) { 94 | var x = random() * canvas_width, //随机位置 95 | y = random() * canvas_height, 96 | xa = 2 * random() - 1, //随机运动方向 97 | ya = 2 * random() - 1; 98 | random_lines.push({ 99 | x: x, 100 | y: y, 101 | xa: xa, 102 | ya: ya, 103 | max: 6000 //沾附距离 104 | }); 105 | } 106 | //0.1秒后绘制 107 | setTimeout(function () { 108 | draw_canvas(); 109 | }, 100); 110 | }(); -------------------------------------------------------------------------------- /src/components/common/Add.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 39 | 40 | 50 | -------------------------------------------------------------------------------- /src/components/common/BackgroundEffect.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 37 | 38 | -------------------------------------------------------------------------------- /src/components/common/LeaveMsg.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 40 | 41 | -------------------------------------------------------------------------------- /src/components/common/Music.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 67 | 68 | 94 | -------------------------------------------------------------------------------- /src/components/common/Notice.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 34 | 35 | 46 | -------------------------------------------------------------------------------- /src/components/common/People.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 31 | 32 | -------------------------------------------------------------------------------- /src/components/common/Sort.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 47 | 48 | 58 | -------------------------------------------------------------------------------- /src/components/common/ToHot.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 28 | 29 | 39 | -------------------------------------------------------------------------------- /src/components/common/ToMall.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 33 | 34 | 44 | -------------------------------------------------------------------------------- /src/components/common/ToNav.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 37 | 38 | 48 | -------------------------------------------------------------------------------- /src/components/common/Weather.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 45 | 46 | 56 | -------------------------------------------------------------------------------- /src/components/dialog/AddBoxDialog.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 133 | 134 | -------------------------------------------------------------------------------- /src/components/dialog/AddListDialog.vue: -------------------------------------------------------------------------------- 1 | 51 | 52 | 130 | 131 | -------------------------------------------------------------------------------- /src/components/dialog/AddSearchSiteDialog.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 108 | 109 | -------------------------------------------------------------------------------- /src/components/dialog/ImageDialog.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 90 | 91 | -------------------------------------------------------------------------------- /src/components/dialog/MsgReplyDialog.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 60 | 61 | -------------------------------------------------------------------------------- /src/components/dialog/MusicSettingDialog.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 131 | 132 | 152 | -------------------------------------------------------------------------------- /src/components/dialog/NoticeDialog.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 35 | 36 | -------------------------------------------------------------------------------- /src/components/dialog/UpdateBoxDialog.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 134 | 135 | -------------------------------------------------------------------------------- /src/components/dialog/UpdateListDialog.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 152 | 153 | 156 | -------------------------------------------------------------------------------- /src/components/dialog/UpdateSearchSiteDialog.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 111 | 112 | -------------------------------------------------------------------------------- /src/components/dialog/ViewMsgDialog.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 45 | 46 | -------------------------------------------------------------------------------- /src/components/dialog/WeatherDialog.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 62 | 63 | 69 | -------------------------------------------------------------------------------- /src/components/dialog/WechatDialog.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 34 | 35 | -------------------------------------------------------------------------------- /src/components/drawer/AddDrawer.vue: -------------------------------------------------------------------------------- 1 | 58 | 59 | 157 | 158 | 163 | -------------------------------------------------------------------------------- /src/components/item/MsgItem.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 27 | 28 | -------------------------------------------------------------------------------- /src/components/item/NavItem.vue: -------------------------------------------------------------------------------- 1 | 52 | 53 | 114 | 115 | 268 | -------------------------------------------------------------------------------- /src/components/user/Bottom.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 29 | 30 | -------------------------------------------------------------------------------- /src/components/user/Left.vue: -------------------------------------------------------------------------------- 1 | 66 | 67 | 168 | 169 | 180 | -------------------------------------------------------------------------------- /src/components/user/Top.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 40 | 41 | -------------------------------------------------------------------------------- /src/config/TransformData.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | 3 | export default new Vue(); -------------------------------------------------------------------------------- /src/config/code.js: -------------------------------------------------------------------------------- 1 | export const SUCCESS_CODE = 1000; 2 | export const ADD_SUCCESS_CODE = 30002; 3 | -------------------------------------------------------------------------------- /src/config/config.js: -------------------------------------------------------------------------------- 1 | const UPDATE_NOTE_SHOW_KEY = 'updateNote-v26'; 2 | const MAIN_URL = 'https://ujuji.com'; 3 | const BASE_URL = 'https://[suffix].ujuji.com/'; 4 | const IMAGE_URL = 'http://api.misiai.com/favicon/api1.php?bgc=[bgColor]&color=[textColor]&str=[text]'; 5 | const FAVICON_API_URL = 'https://i.olsh.me/icon?size=80..120..200&url='; 6 | const BING_IMAGE_URL = 'https://tool.misiyu.cn/api/bing'; 7 | const HUA_WEI_CLOUD_URL = 'https://www.misiyu.cn/article/157.html'; 8 | const TAOKE_URL = [ 9 | 'https://shop.misiai.com', 10 | 'https://mall.misiai.com' 11 | ]; 12 | const MALL_URL='https://mall.misiai.com' 13 | const MOBILE_BACKGROUND_COLOR = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADsAAAA0CAIAAAC7EdcxAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABOSURBVGhD7c5BDQAwEAShGlv/tqqCxyWDAt6uaew19hp7jb3GXmOvsdfYa+w19hp7jb3GXmOvsdfYa+w19hp7jb3GXmOvsdfYa+xdG28fFp+RnV5AzWkAAAAASUVORK5CYII='; 14 | // const FAVICON_API_URL = 'https://api.byi.pw/favicon/?url='; 15 | const BING_IMG_API_URL = 'https://api2.misiai.com/bing/v1/today'; 16 | // const BING_IMG_API_URL = 'https://common.misiai.com/public/bing'; 17 | const ANIME_IMG_API_URL = 'https://api.ixiaowai.cn/api/api.php'; 18 | const SEARCH_SITE_URL = 'https://search.ujuji.com/'; 19 | const NAV_SITE_URL = 'https://nav.ujuji.com/'; 20 | const LZPAN_URL = 'https://lzpan.com' 21 | const HOT_HUB_URL = 'https://ihothub.com/'; 22 | const KEY_ORDER = 'box_orders'; 23 | const KEY_SEARCH_INDEX = 'key_search_site_index'; 24 | const KEY_BACKGROUND_IMAGE = 'key_background_image' 25 | const EVENT_SET_BGI = 'event_set_background_image' 26 | 27 | exports.MALL_URL = MALL_URL; 28 | exports.EVENT_SET_BGI = EVENT_SET_BGI; 29 | exports.KEY_BACKGROUND_IMAGE = KEY_BACKGROUND_IMAGE; 30 | exports.LZPAN_URL = LZPAN_URL; 31 | exports.NAV_SITE_URL = NAV_SITE_URL; 32 | exports.HOT_HUB_URL = HOT_HUB_URL; 33 | exports.SEARCH_SITE_URL = SEARCH_SITE_URL; 34 | exports.KEY_SEARCH_INDEX = KEY_SEARCH_INDEX; 35 | exports.ANIME_IMG_API_URL = ANIME_IMG_API_URL; 36 | exports.BING_IMG_API_URL = BING_IMG_API_URL; 37 | exports.KEY_ORDER = KEY_ORDER; 38 | exports.MAIN_URL = MAIN_URL; 39 | exports.MOBILE_BACKGROUND_COLOR = MOBILE_BACKGROUND_COLOR; 40 | exports.UPDATE_NOTE_SHOW_KEY = UPDATE_NOTE_SHOW_KEY; 41 | exports.BASE_URL = BASE_URL; 42 | exports.HUA_WEI_CLOUD_URL = HUA_WEI_CLOUD_URL; 43 | exports.TAOKE_URL = TAOKE_URL; 44 | exports.IMAGE_URL = IMAGE_URL; 45 | exports.FAVICON_API_URL = FAVICON_API_URL; 46 | exports.BING_IMGAE_URL = BING_IMAGE_URL; 47 | -------------------------------------------------------------------------------- /src/config/events.js: -------------------------------------------------------------------------------- 1 | export const EVENT_WEATHER = 'event_weather'; 2 | export const EVENT_OPEN_WEATHER_DIALOG = 'openWeatherDialog'; 3 | export const EVENT_CLOSE_WEATHER_DIALOG = 'closeWeatherDialog'; 4 | -------------------------------------------------------------------------------- /src/config/getInfo.js: -------------------------------------------------------------------------------- 1 | function getUserInfo() { 2 | let d = localStorage.getItem('userInfo'); 3 | return JSON.parse(d) || []; 4 | 5 | } 6 | 7 | function isMobile() { 8 | const sUserAgent = navigator.userAgent.toLowerCase(); 9 | return /ipad|iphone|midp|rv:1.2.3.4|ucweb|android|windows ce|windows mobile/.test(sUserAgent); 10 | } 11 | 12 | exports.getUserInfo = getUserInfo(); 13 | exports.isMobile = isMobile(); -------------------------------------------------------------------------------- /src/config/guide.json: -------------------------------------------------------------------------------- 1 | { 2 | "guides": [ 3 | { 4 | "url": "https://www.misiyu.cn/article/149.html", 5 | "title": "[优聚集]用户使用说明书" 6 | }, 7 | { 8 | "url": "https://www.misiyu.cn/article/150.html", 9 | "title": "[优聚集]用户使用与免责申明" 10 | }, 11 | { 12 | "url": "https://www.misiyu.cn/article/151.html", 13 | "title": "[优聚集]用户背景音乐和背景图片设置" 14 | }, 15 | { 16 | "url": "https://www.misiyu.cn/article/152.html", 17 | "title": "[优聚集]首页添加搜索站点" 18 | }, 19 | { 20 | "url": "https://www.misiyu.cn/article/154.html", 21 | "title": "[优聚集]支持设置盒子的颜色了(额外说明)" 22 | }, 23 | { 24 | "url": "https://www.misiyu.cn/article/164.html", 25 | "title": "[优聚集]快捷添加一个站点链接" 26 | } 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /src/config/http.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import router from "../router"; 3 | import store from "../store"; 4 | 5 | let url; 6 | if (process.env.NODE_ENV === 'production') { 7 | url = 'https://api.ujuji.com' 8 | } else { 9 | url = 'http://localhost:4037' 10 | } 11 | axios.defaults.baseURL = url; 12 | axios.defaults.headers.common['Content-Type'] = 'application/json'; 13 | // axios.defaults.headers.common['Authorization'] = store.state.token; 14 | axios.interceptors.request.use( 15 | config => { 16 | config.headers['Authorization'] = 'Bearer ' + store.state.token; 17 | return config; 18 | } 19 | ) 20 | axios.interceptors.response.use( 21 | (responses) => responses, 22 | (error) => { 23 | if (error.response && error.response.status === 403) { 24 | console.log(error); 25 | localStorage.removeItem('token'); 26 | router.push({name: "UserLogin"}); 27 | return new Promise(() => { 28 | }) // pending的promise,中止promise链 29 | } 30 | } 31 | ); 32 | export default axios; -------------------------------------------------------------------------------- /src/config/keys.js: -------------------------------------------------------------------------------- 1 | export const KEY_WEATHER = 'key_weather'; 2 | -------------------------------------------------------------------------------- /src/config/strings.js: -------------------------------------------------------------------------------- 1 | export const REQ_BOXES_DATA_ERROR = '请求分类数据错误' 2 | export const TOKEN_PARAM_REQUIRED = '您的请求未携带token,所以本次请求无效' 3 | export const REQ_DATA_ERROR = '本次请求失败,请稍后重试' 4 | export const TEXT_COPY_SUCCESS = '复制成功' 5 | export const TEXT_COPY_FAIL = '复制失败' 6 | -------------------------------------------------------------------------------- /src/config/updateNotes.json: -------------------------------------------------------------------------------- 1 | { 2 | "activities": [ 3 | { 4 | "content": "上线快捷添加链接功能", 5 | "timestamp": "2020-12-31 20:58:01", 6 | "color": "#0bbd87" 7 | }, 8 | { 9 | "content": "登录用户可在首页直接添加站点", 10 | "timestamp": "2020-12-12 14:44:01", 11 | "color": "#0bbd87" 12 | }, 13 | { 14 | "content": "后台可设置是否显示站点前的图标", 15 | "timestamp": "2020-09-19 09:44:01", 16 | "color": "#0bbd87" 17 | }, 18 | { 19 | "content": "更换天气预报,现在首页可设置天气预报地区了!", 20 | "timestamp": "2020-08-14 16:35:21", 21 | "color": "#0bbd87" 22 | }, 23 | { 24 | "content": "现在支持导入浏览器书签了(后缀为:.html)", 25 | "timestamp": "2020-08-12 15:35:21", 26 | "color": "#0bbd87" 27 | }, 28 | { 29 | "content": "现在可导入盒子(书签)了,尽情测试【请勿滥用此功能】", 30 | "timestamp": "2020-08-05 15:35:21", 31 | "color": "#0bbd87" 32 | }, 33 | { 34 | "content": "后台可以设置带有密码的盒子是否显示在首页(用户自己登录了,那么默认肯定也会显示且不需要输入密码)", 35 | "timestamp": "2020-07-22 11:35:21", 36 | "color": "#0bbd87" 37 | }, 38 | { 39 | "content": "现在登录用户可以直接看到需要输入密码的盒子内容,游客则需要输入密码", 40 | "timestamp": "2020-07-16 11:35:21", 41 | "color": "#0bbd87" 42 | }, 43 | { 44 | "content": "增加手机端背景可单独设置的功能,由于浏览器原因,在手机端背景图片并不能很好的固定,导致很难看。所以可单独为手机端设置一张合适的背景", 45 | "timestamp": "2020-07-07 07:35:21", 46 | "color": "#0bbd87" 47 | }, 48 | { 49 | "content": "增加随机背景的选择,目前有两个:【必应美图】【二次元美图】,前者每日一换,后者随机更换", 50 | "timestamp": "2020-07-06 11:11:42", 51 | "color": "#0bbd87" 52 | }, 53 | { 54 | "content": "用户可自定义首页的背景音乐啦~没有自定义的,就使用后台站长设定的音乐", 55 | "timestamp": "2020-07-05 08:45:52", 56 | "color": "#0bbd87" 57 | }, 58 | { 59 | "content": "增加找回密码功能(通过电子邮箱)", 60 | "timestamp": "2020-07-02 09:41:49", 61 | "color": "#0bbd87" 62 | }, 63 | { 64 | "content": "新增两种导出方式(Csv、TXT),欢迎体验导出功能,不让辛苦添加的网址因网站问题而丢失", 65 | "timestamp": "2020-06-29 17:16:59", 66 | "color": "#0bbd87" 67 | }, 68 | { 69 | "content": "1、完善体验,添加、修改时,可以直接回车了,不用点击【提交】按钮。2、更改验证码样式,简单明了。", 70 | "timestamp": "2020-06-28 11:36:15", 71 | "color": "#0bbd87" 72 | }, 73 | { 74 | "content": "首页,用户可拖动盒子排序,来自定义盒子的顺序", 75 | "timestamp": "2020-06-27 18:34:44", 76 | "color": "#0bbd87" 77 | }, 78 | { 79 | "content": "首页音乐设定: 默认自动播放,用户手动点击暂停了,那么下次就不会自动播放了(就需要手动)", 80 | "timestamp": "2020-06-27 11:32:05", 81 | "color": "#0bbd87" 82 | }, 83 | { 84 | "content": "目前可以设置搜索站点的文字颜色了,路径:站点配置->颜色配置->站点搜索", 85 | "timestamp": "2020-06-17 18:07:31", 86 | "color": "#0bbd87" 87 | }, 88 | { 89 | "content": "增加盒子颜色的配置,这样对于背景图片就有更好的选择了。【对于这点,有些颜色知识需要额外说一下,可看[管理首页]的指导文章】", 90 | "timestamp": "2020-06-16 13:16:54", 91 | "color": "#0bbd87" 92 | }, 93 | { 94 | "content": "目前需要用户手动点击音乐按钮,首页才会播放音乐,这样也许对不喜欢音乐的用户,是个好事", 95 | "timestamp": "2020-06-13 20:37:58", 96 | "color": "#0bbd87" 97 | }, 98 | { 99 | "content": "增加首页的搜索网站自定义", 100 | "timestamp": "2020-06-11 14:12:26", 101 | "color": "#0bbd87" 102 | }, 103 | { 104 | "content": "增加留言功能,有bug请到主站留言", 105 | "timestamp": "2020-06-10 19:56:41", 106 | "color": "#0bbd87" 107 | }, 108 | { 109 | "content": "增加导出功能,成果不因意外而白费,现在可自行导出备份啦!", 110 | "timestamp": "2020-06-09 08:37:54", 111 | "color": "#0bbd87" 112 | }, 113 | { 114 | "content": "增加长公告设置,原来的变为站点欢迎提示", 115 | "timestamp": "2020-06-08 13:27:37", 116 | "color": "#0bbd87" 117 | }, 118 | { 119 | "content": "现在可以设置导航首页的背景音乐啦!", 120 | "timestamp": "2020-06-06 16:55:30", 121 | "color": "#0bbd87" 122 | }, 123 | { 124 | "content": "现在可以给盒子设置访问密码啦,需要输入密码才能访问盒子内容(请勿滥用此功能,否则会被封号)", 125 | "timestamp": "2020-06-06 07:33:12", 126 | "color": "#0bbd87" 127 | }, 128 | { 129 | "content": "增加公告模块,现在可以给访问导航的朋友设置一段话啦", 130 | "timestamp": "2020-06-3 17:44:35", 131 | "color": "#0bbd87" 132 | }, 133 | { 134 | "content": "增加盒子、列表的本地检索(搜索标题)功能", 135 | "timestamp": "2020-06-3 10:53:03", 136 | "color": "#0bbd87" 137 | }, 138 | { 139 | "content": "完全开放二级域名权限,现在不会跳转到顶级域名后缀", 140 | "timestamp": "2020-06-1 09:03:10", 141 | "color": "#0bbd87" 142 | }, 143 | { 144 | "content": "支持设置盒子、站点列表的颜色", 145 | "timestamp": "2020-05-31 12:02:55", 146 | "color": "#0bbd87" 147 | }, 148 | { 149 | "content": "不指定站点图标的话,就默认尝试使用其站点自身的图标", 150 | "timestamp": "2020-05-28 09:59:47", 151 | "color": "#0bbd87" 152 | }, 153 | { 154 | "content": "可配置站点标题、描述的文字颜色", 155 | "timestamp": "2020-05-28 09:59:47", 156 | "color": "#0bbd87" 157 | } 158 | ] 159 | } 160 | -------------------------------------------------------------------------------- /src/element/index.js: -------------------------------------------------------------------------------- 1 | // 导入自己需要的组件 2 | import { 3 | Notification, Loading, Message, Upload, Divider, 4 | Card, Form, FormItem, Input, Button, Table, TableColumn, Badge, MessageBox, 5 | Tooltip, Select, Option, Alert, InputNumber, ColorPicker, Timeline, TimelineItem, 6 | RadioGroup, Radio, 7 | Backtop, Tag, Pagination, Checkbox, Step, Steps, Switch, 8 | Dialog, Row, Col, TabPane, Tabs, MenuItem, Submenu, Menu, Drawer 9 | } from 'element-ui' 10 | 11 | const element = { 12 | install: function (Vue) { 13 | Vue.use(Divider); 14 | Vue.use(Drawer); 15 | Vue.use(Upload); 16 | Vue.use(Radio); 17 | Vue.use(RadioGroup); 18 | Vue.use(Switch); 19 | Vue.use(Checkbox); 20 | Vue.use(Steps); 21 | Vue.use(Step); 22 | Vue.use(Pagination); 23 | Vue.use(Tag); 24 | Vue.use(Timeline); 25 | Vue.use(Backtop); 26 | Vue.use(TimelineItem); 27 | Vue.use(ColorPicker); 28 | Vue.use(InputNumber); 29 | Vue.use(Alert); 30 | Vue.use(Option); 31 | Vue.use(Select); 32 | Vue.use(Badge); 33 | Vue.use(Tooltip); 34 | Vue.use(Table); 35 | Vue.use(TableColumn); 36 | Vue.use(Loading.directive); 37 | Vue.prototype.$notify = Notification; 38 | Vue.prototype.$confirm = MessageBox.confirm; 39 | Vue.prototype.$message = Message; 40 | Vue.use(Dialog); 41 | Vue.use(Row); 42 | Vue.use(Col); 43 | Vue.use(TabPane); 44 | Vue.use(Tabs); 45 | Vue.use(Submenu); 46 | Vue.use(Card); 47 | Vue.use(Menu); 48 | Vue.use(MenuItem); 49 | Vue.use(FormItem); 50 | Vue.use(Form); 51 | Vue.use(Input); 52 | Vue.use(Button); 53 | } 54 | }; 55 | export default element 56 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import store from './store' 5 | import axios from './config/http'; 6 | 7 | Vue.config.productionTip = false 8 | 9 | import VueDND from 'awe-dnd'; 10 | 11 | 12 | Vue.use(VueDND);//拖拽排序 13 | Vue.prototype.$http = axios; 14 | // css样式还是需要全部引入 15 | import 'element-ui/lib/theme-chalk/index.css' 16 | import element from './element/index'; 17 | 18 | // 重置样式 19 | import "./assets/css/reset.scss"; 20 | 21 | Vue.use(element); 22 | 23 | router.beforeEach((to, from, next) => { 24 | if (to.meta.title) { 25 | document.title = to.meta.title; 26 | } 27 | next(); 28 | }); 29 | 30 | // iconfont 31 | import "./assets/iconfont/iconfont.css"; 32 | // global 33 | import "./assets/css/global.scss"; 34 | 35 | new Vue({ 36 | router, 37 | store, 38 | render: h => h(App) 39 | }).$mount('#app') 40 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | // import Home from '../views/Home.vue' 4 | // import UserHome from "../views/user/UserHome"; 5 | // import User from "../views/User"; 6 | import Index from "../views/Index"; 7 | 8 | Vue.use(VueRouter) 9 | 10 | const routes = [ 11 | // { 12 | // path: '/', 13 | // name: 'Home', 14 | // component: Home 15 | // }, 16 | { 17 | path: '/user', 18 | component: () => import("../views/User"), 19 | meta: { 20 | title: '控制台 | 优聚集' 21 | }, 22 | children: [ 23 | { 24 | path: '/', 25 | name: 'HomeConfig', 26 | component: () => import("../views/user/Home"), 27 | meta: { 28 | title: '控制台首页 | 优聚集' 29 | }, 30 | }, 31 | { 32 | path: '/profile', 33 | name: 'Profile', 34 | component: () => import("../views/user/Profile"), 35 | meta: { 36 | title: '个人中心 | 优聚集' 37 | }, 38 | }, 39 | { 40 | path: 'siteConfig', 41 | name: 'SiteConfig', 42 | component: () => import("../views/user/SiteConfig"), 43 | meta: { 44 | title: '站点配置 | 优聚集' 45 | }, 46 | }, 47 | { 48 | path: 'boxConfig', 49 | name: 'BoxConfig', 50 | component: () => import("../views/user/BoxConfig"), 51 | meta: { 52 | title: '盒子管理 | 优聚集' 53 | }, 54 | }, 55 | { 56 | path: 'importConfig', 57 | name: 'ImportConfig', 58 | component: () => import("../views/user/ImportConfig"), 59 | meta: { 60 | title: '导入功能 | 优聚集' 61 | }, 62 | }, 63 | { 64 | path: 'exportConfig', 65 | name: 'ExportConfig', 66 | component: () => import("../views/user/ExportConfig"), 67 | meta: { 68 | title: '导出功能 | 优聚集' 69 | }, 70 | }, 71 | { 72 | path: 'msgConfig', 73 | name: 'MsgConfig', 74 | component: () => import("../views/user/MsgConfig"), 75 | meta: { 76 | title: '留言管理 | 优聚集' 77 | }, 78 | }, 79 | { 80 | path: 'searchSiteConfig', 81 | name: 'SearchSiteConfig', 82 | component: () => import("../views/user/SearchSiteConfig"), 83 | meta: { 84 | title: '搜索站点配置 | 优聚集' 85 | }, 86 | }, 87 | { 88 | path: 'aboutUs', 89 | name: 'AboutUs', 90 | component: () => import("../views/user/AboutUs"), 91 | meta: { 92 | title: '关于我们 | 优聚集' 93 | }, 94 | }, 95 | { 96 | path: 'noticeConfig', 97 | name: 'NoticeConfig', 98 | component: () => import("../views/user/NoticeConfig"), 99 | meta: { 100 | title: '公告配置 | 优聚集' 101 | }, 102 | }, 103 | { 104 | path: 'listConfig', 105 | name: 'ListConfig', 106 | component: () => import("../views/user/ListConfig"), 107 | meta: { 108 | title: '列表管理 | 优聚集' 109 | }, 110 | }, 111 | { 112 | path: 'modifyPass', 113 | name: 'ModifyPass', 114 | component: () => import("../views/user/ModifyPass"), 115 | meta: { 116 | title: '修改密码 | 优聚集' 117 | }, 118 | }, 119 | { 120 | path: 'updateNote', 121 | name: 'UpdateNote', 122 | component: () => import("../views/user/UpdateNote"), 123 | meta: { 124 | title: '更新日记 | 优聚集' 125 | }, 126 | }, 127 | ] 128 | }, 129 | { 130 | path: '/search', 131 | name: 'Search', 132 | component: () => import("../views/Search"), 133 | meta: { 134 | title: '搜索 | 优聚集' 135 | }, 136 | }, 137 | { 138 | path: '/token_add', 139 | name: 'TokenAdd', 140 | component: () => import("../views/TokenAdd"), 141 | meta: { 142 | title: '快速添加链接 | 优聚集' 143 | }, 144 | }, 145 | { 146 | path: '/userLogin', 147 | name: 'UserLogin', 148 | component: () => import("../views/user/UserLogin"), 149 | meta: { 150 | title: '用户登录 | 优聚集' 151 | }, 152 | }, 153 | { 154 | path: '/findPass', 155 | name: 'FindPass', 156 | component: () => import("../components/step/FindPassStep"), 157 | meta: { 158 | title: '找回密码 | 优聚集' 159 | }, 160 | }, 161 | { 162 | path: '/', 163 | name: 'Index', 164 | component: Index, 165 | meta: { 166 | title: '优质网站 | 优聚集' 167 | }, 168 | // children: [ 169 | // { 170 | // path: '/:suffix', 171 | // name: 'Index2', 172 | // component: Index, 173 | // meta: { 174 | // title: '优质网站 | 优聚集' 175 | // }, 176 | // } 177 | // ] 178 | } 179 | ] 180 | 181 | const router = new VueRouter({ 182 | mode: 'history', 183 | routes 184 | }) 185 | 186 | export default router 187 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import state from "@/store/state"; 4 | import mutations from "@/store/mutations"; 5 | Vue.use(Vuex) 6 | 7 | export default new Vuex.Store({ 8 | state, 9 | mutations, 10 | actions: {}, 11 | modules: {} 12 | }) 13 | -------------------------------------------------------------------------------- /src/store/mutations.js: -------------------------------------------------------------------------------- 1 | export default { 2 | changeSort(state, val) { 3 | state.sort = val; 4 | }, 5 | changeCity(state, val) { 6 | state.city = val; 7 | }, 8 | changeUserId(state, val) { 9 | state.userId = val; 10 | }, 11 | changePlayMusic(state, val) { 12 | state.playMusic = val; 13 | }, 14 | changeSiteUserId(state, val) { 15 | state.siteUserId = val; 16 | }, 17 | changeBackgroundImage(state, val) { 18 | state.backgroundImage = val; 19 | }, 20 | changeBackgroundMusic(state, val) { 21 | state.backgroundMusic = val; 22 | }, 23 | changeIndexLoading(state, val) { 24 | state.indexLoading = val; 25 | }, 26 | changeSuffix(state, val) { 27 | state.suffix = val; 28 | }, 29 | changeDefaultSuffix(state, val) { 30 | state.defaultSuffix = val; 31 | }, 32 | changeUsername(state, val) { 33 | state.username = val; 34 | }, 35 | changeToken(state, val) { 36 | state.token = val; 37 | }, 38 | 39 | changeUserInfo(state, val) { 40 | state.userInfo = val; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/store/state.js: -------------------------------------------------------------------------------- 1 | import {KEY_WEATHER} from "@/config/keys"; 2 | 3 | const state = { 4 | token: '', 5 | userInfo: {}, 6 | userId: -1, 7 | username: '', 8 | suffix: '', 9 | city: '', 10 | defaultSuffix: '', 11 | indexLoading: false, 12 | backgroundImage: '', 13 | backgroundMusic: '', 14 | siteUserId: -1, 15 | playMusic: false, 16 | sort: false, 17 | } 18 | 19 | let city = localStorage.getItem(KEY_WEATHER) || ''; 20 | if (city) { 21 | state.city = city 22 | } 23 | 24 | export default state 25 | -------------------------------------------------------------------------------- /src/util/isMobile.js: -------------------------------------------------------------------------------- 1 | function isMobile() { 2 | const sUserAgent = navigator.userAgent.toLowerCase(); 3 | return /ipad|iphone|midp|rv:1.2.3.4|ucweb|android|windows ce|windows mobile/.test(sUserAgent); 4 | } 5 | 6 | export default isMobile; -------------------------------------------------------------------------------- /src/util/utils.js: -------------------------------------------------------------------------------- 1 | function toFloat(value) { 2 | 3 | value = Math.round(parseFloat(value) * 100) / 100; 4 | 5 | if (value.toString().indexOf(".") < 0) { 6 | 7 | value = value.toString() + ".00"; 8 | 9 | } 10 | return value; 11 | } 12 | 13 | function getWeekDate() { 14 | let now = new Date(); 15 | let day = now.getDay(); 16 | let weeks = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"]; 17 | return weeks[day]; 18 | } 19 | 20 | function getScrollTop() { 21 | var scrollTop = 0, bodyScrollTop = 0, documentScrollTop = 0; 22 | if (document.body) { 23 | bodyScrollTop = document.body.scrollTop; 24 | } 25 | if (document.documentElement) { 26 | documentScrollTop = document.documentElement.scrollTop; 27 | } 28 | scrollTop = (bodyScrollTop - documentScrollTop > 0) ? bodyScrollTop : documentScrollTop; 29 | return scrollTop; 30 | } 31 | 32 | //文档的总高度 33 | 34 | function getScrollHeight() { 35 | var scrollHeight = 0, bodyScrollHeight = 0, documentScrollHeight = 0; 36 | if (document.body) { 37 | bodyScrollHeight = document.body.scrollHeight; 38 | } 39 | if (document.documentElement) { 40 | documentScrollHeight = document.documentElement.scrollHeight; 41 | } 42 | scrollHeight = (bodyScrollHeight - documentScrollHeight > 0) ? bodyScrollHeight : documentScrollHeight; 43 | return scrollHeight; 44 | } 45 | 46 | //浏览器视口的高度 47 | 48 | function getWindowHeight() { 49 | var windowHeight = 0; 50 | if (document.compatMode === "CSS1Compat") { 51 | windowHeight = document.documentElement.clientHeight; 52 | } else { 53 | windowHeight = document.body.clientHeight; 54 | } 55 | return windowHeight; 56 | } 57 | 58 | function jumpUrl(url) { 59 | let ok = window.open(url, '_blank') 60 | if (!ok) { 61 | window.location.href = url; 62 | } 63 | } 64 | 65 | 66 | //是否是手机 67 | function isMobile() { 68 | const sUserAgent = navigator.userAgent.toLowerCase(); 69 | return /ipad|iphone|midp|rv:1.2.3.4|ucweb|android|windows ce|windows mobile/.test(sUserAgent); 70 | } 71 | 72 | //是否是平板 73 | function isIpad() { 74 | let ua = navigator.userAgent.toLowerCase(); 75 | return ua.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); 76 | 77 | } 78 | 79 | function resetNoteVer(nowVer) { 80 | let exec = /^updateNote-v(\d+)$/ig.exec(nowVer); 81 | // console.log(exec); 82 | let n = parseInt(exec[1]); 83 | // console.log(n); 84 | for (let i = 0; i < n; i++) { 85 | localStorage.removeItem(nowVer.replace(n, i)); 86 | } 87 | } 88 | 89 | exports.resetNoteVer = resetNoteVer; 90 | exports.isIpad = isIpad; 91 | exports.isMobile = isMobile; 92 | exports.jumpUrl = jumpUrl; 93 | exports.getWindowHeight = getWindowHeight; 94 | exports.getScrollHeight = getScrollHeight; 95 | exports.getScrollTop = getScrollTop; 96 | exports.toFloat = toFloat; 97 | exports.getWeekDate = getWeekDate; 98 | -------------------------------------------------------------------------------- /src/views/Index.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 102 | 103 | 151 | -------------------------------------------------------------------------------- /src/views/Search.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 41 | 42 | -------------------------------------------------------------------------------- /src/views/TokenAdd.vue: -------------------------------------------------------------------------------- 1 | 50 | 51 | 138 | 139 | 151 | -------------------------------------------------------------------------------- /src/views/User.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 97 | 98 | 101 | -------------------------------------------------------------------------------- /src/views/index/Footer.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 66 | 67 | 96 | -------------------------------------------------------------------------------- /src/views/index/Header.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 81 | 82 | 116 | -------------------------------------------------------------------------------- /src/views/index/Nav.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 185 | 186 | -------------------------------------------------------------------------------- /src/views/index/RightBar.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 63 | 64 | 83 | -------------------------------------------------------------------------------- /src/views/index/Search.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 105 | 106 | 157 | -------------------------------------------------------------------------------- /src/views/user/AboutUs.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 40 | 41 | -------------------------------------------------------------------------------- /src/views/user/ExportConfig.vue: -------------------------------------------------------------------------------- 1 | 49 | 50 | 201 | 202 | 230 | -------------------------------------------------------------------------------- /src/views/user/Home.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 69 | 70 | -------------------------------------------------------------------------------- /src/views/user/ImportConfig.vue: -------------------------------------------------------------------------------- 1 | 58 | 59 | 199 | 200 | 287 | -------------------------------------------------------------------------------- /src/views/user/ModifyPass.vue: -------------------------------------------------------------------------------- 1 | 34 | 35 | 99 | 100 | -------------------------------------------------------------------------------- /src/views/user/NoticeConfig.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 86 | 87 | -------------------------------------------------------------------------------- /src/views/user/SearchSiteConfig.vue: -------------------------------------------------------------------------------- 1 | 66 | 67 | 147 | 148 | -------------------------------------------------------------------------------- /src/views/user/UpdateNote.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 40 | 41 | 46 | --------------------------------------------------------------------------------