Commit 6052ae75 authored by mahui's avatar mahui

init

parent 39129583
> 1%
last 2 versions
not dead
root = true
[*]
charset = utf-8
indent_style = tab
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# pc
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
This diff is collapsed.
{
"name": "pc",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"axios": "^0.24.0",
"core-js": "^3.6.5",
"dayjs": "^1.10.7",
"element-plus": "^2.0.1",
"pinia": "^2.0.14",
"vue": "^3.0.0",
"vue-router": "^4.0.0-0",
"vue3-photo-preview": "^0.1.6"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0",
"less": "^3.0.4",
"less-loader": "^5.0.0"
}
}
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
<template>
<router-view v-slot="{Component}">
<component :is="Component">
</component>
</router-view>
</template>
<style lang="less">
@import url('./assets/public.css');
#app {
position: relative;
width: 100vw;
height: 100vh;
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
display: flex;
flex-direction: column;
overflow: hidden;
font-size: 14px;
}
</style>
import api from './methods/index'
import axios from 'axios';
import qs from 'qs';
import { ElMessage } from 'element-plus'
import {useStore} from '@/store/modules/app';
import myPublic from '@/utils/public';
let id = 0;
const API_HOST = '';
const list = [
'phone/sms/sendCode',
'phone/login/login'
];
axios.interceptors.request.use(config => {
// loading
return config
}, error => {
return Promise.reject(error)
});
axios.interceptors.response.use(response => {
// console.log('响应拦截器',response)
return response
}, error => {
return Promise.resolve(error.response)
});
function checkStatus(response,url,record) {
// loading
// 如果http状态码正常,则直接返回数据
if (response && (response.status === 200 || response.status === 304 || response.status === 400)) {
console.log(`response`,record,url+' ',response.data);
console.timeEnd(`request ${record}`);
return response.data
// 如果不需要除了data之外的数据,可以直接 return response.data
}
// 异常状态下,把错误信息返回去
console.err(`response`,record,url+' ',response);
console.timeEnd(`request ${record}`);
return {
status: -404,
msg: '网络异常或服务端出错'
}
}
// 验证code
function checkCode(res,url) {
// 如果code异常(这里已经包括网络错误,服务器错误,后端抛出的错误),可以弹出一个错误提示,告诉用户
if (res.status === -404) {
ElMessage({
type:'warning',
message: res.msg +'方法名:'+ url || '服务器出错 方法名:'+ url,
}).then(() => {
// on close
});
}
if (res.code == 1000) {
localStorage.removeItem('token');
location.href = location.origin+location.pathname+'#/login';
return res
}
if(res.code!=0){
ElMessage({
type:'warning',
message: res.msg,
}).then(() => {
// on close
});
return res
}
return res
}
export default {
post(url,data, config = { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }){
let record = id;
if(list.indexOf(url)==-1){
let token = myPublic.getStorage('token');
config['token'] = token;
}
console.log(`request`,record,url+' ',data);
console.time(`request ${record}`);
id++;
return axios({
method: 'post',
baseURL: API_HOST,
url,
data: qs.stringify(data),
headers: config
}).then(response =>{
return checkStatus(response,url,record);
}).then( res =>{
return checkCode(res, url)
}).catch(function(err) {
console.log(`err`,record,url+' ',err);
id++;
})
},
upload(url,data, config = { 'Content-Type': 'multipart/form-data' }){
let record = id;
console.log(`request`,record,url+' ',data);
console.time(`request ${record}`);
id++;
return axios({
method: 'post',
baseURL: API_HOST,
url,
data: data,
headers: config
}).then(response =>{
return checkStatus(response,url,record);
}).then( res =>{
return checkCode(res, url)
}).catch(function(err) {
console.log(`err`,record,url+' ',err);
id++;
})
},
}
import test from './test';
export default {
test:test,
}
import http from '../getData';
export default {
//待检查车辆
// getToCheck(params) {
// return http.post('phone/back_detail/getToCheck', params)
// }
}
body,
html {
width: 100%;
min-height: 100%;
font-family: Helvetica Neue For Number, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Helvetica Neue, Helvetica, Arial, sans-serif;
}
body{
overflow: hidden;
font-size: 14px;
}
body,
html,
h4,
ul,
ol,
li,
a,
div,
input,
p,
textarea,
button {
padding: 0;
margin: 0;
list-style: none;
font-style: normal;
text-decoration: none;
border: none;
font-family: "Microsoft Yahei", sans-serif;
outline: none;
-webkit-tap-highlight-color: rgba(255, 255, 255, 0);
}
input,
textarea {
-webkit-user-select: auto;
/*webkit浏览器*/
font-size: 14px;
padding: 0;
}
textarea:disabled{
-webkit-text-fill-color: #666;
-webkit-opacity: 1;
background: transparent;
color: #666;
}
input[type="button"],
input[type="submit"],
input[type="search"],
input[type="reset"] {
-webkit-appearance: none;
}
textarea {
-webkit-appearance: none;
}
*::-webkit-scrollbar {
width:4px;
height:8px;
}
*::-webkit-scrollbar-track {
border-radius: 10px;
background-color: #fff;
}
*::-webkit-scrollbar-thumb {
border-radius: 10px;
background-color: #999;
}
*::-webkit-scrollbar-thumb:hover{
background: #bbb;
}
::-webkit-input-placeholder {
/* WebKit browsers */
color: #c7c7cc;
font-size: 14px;
text-align: left;
}
:-moz-placeholder {
/* Mozilla Firefox 4 to 18 */
color: #c7c7cc;
text-align: left;
font-size: 14px;
}
::-moz-placeholder {
/* Mozilla Firefox 19+ */
color: #dedede;
text-align: left;
font-size: 14px;
}
:-ms-input-placeholder {
/* Internet Explorer 10+ */
color: #dedede;
text-align: left;
font-size: 14px;
}
.bg-active.gj-active{
background: #f5f5f5!important;
}
.op-active.gj-active{
opacity:.8
}
.color-active.gj-active{
color:#3396fb;
}
.bg-white{
background: #fff;
}
.disabled_bg{
background: #eee!important;
pointer-events: none;
}
.paddingBottom {
padding-bottom: calc(0.05rem + constant(safe-area-inset-bottom)) !important;
padding-bottom: calc(0.05rem + env(safe-area-inset-bottom)) !important;
}
.androidPaddingBottom{
padding-bottom: .5rem !important;
}
.iosPaddingBottom{
padding-bottom: calc(0.5rem + constant(safe-area-inset-bottom)) !important;
padding-bottom: calc(0.5rem + env(safe-area-inset-bottom)) !important;
}
.user_select{
-webkit-user-select: none;
user-select: none;
overflow: hidden!important;
}
.active:active{
opacity: .8;
}
.no-data{
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
.no-data img{
width: 40%;
}
.van-toast{
width:120px !important;
}
import {createApp} from 'vue'
import App from './App.vue'
import router from './router'
import { store } from '@/store'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import vue3PhotoPreview from 'vue3-photo-preview';
import 'vue3-photo-preview/dist/index.css';
const app = createApp(App);
app.use(vue3PhotoPreview);
app.use(store);
app.use(ElementPlus);
app.use(router);
app.mount('#app');
import {createRouter, createWebHashHistory} from 'vue-router'
import {useStore} from '@/store/modules/app';
import api from '@/api/methods/index'
import myPublic from '@/utils/public'
const routes = [
{
path: '/',
name: 'index',
component: () => import('@/views/index.vue'),
redirect: '/home',
children: [
{
path: 'home',
name: 'home',
meta: {
prop: 'home'
},
component: () => import('@/views/home.vue')
}
]
}
];
const router = createRouter({
history: createWebHashHistory(process.env.BASE_URL),
routes
});
router.beforeEach((to, from, next) => {
const store = useStore();
// let token = myPublic.getStorage('token');
// if(!token){
// if(to.path!='/login'){
// next({path:'/login'})
// }else{
// next();
// }
// }else{
// if(!store.state.token){
// store.commit('token',token);
// }
// if(store.state.firstGo){
//
// }
// next()
// }
next()
});
export default router
import { createPinia } from 'pinia'
const store = createPinia()
export {
store
}
import {defineStore } from 'pinia'
export const useStore = defineStore('app',{
state: ()=> {
return {
firstGo:0,
token:'',
ossInfo:{
},
info:{
username:'银河环卫工',
area:{
areaName:'青山湖街道'
}
},
tabs:[
{
icon:'home',
selected_icon:'home-selected',
name:'首页',
show:true,
path:'/home',
key:'home'
},{
icon:'check',
selected_icon:'check-selected',
name:'签到',
show:true,
path:'/check',
key:'check'
},{
icon:'scores',
selected_icon:'scores-selected',
name:'积分榜',
show:true,
path:'/scores',
key:'scores'
},{
icon:'my',
selected_icon:'my-selected',
name:'我的',
show:true,
path:'/my',
key:'my'
}
],
active:''
}
},
actions: {
oss_info(data){
this.ossInfo = data;
},
ACTIVE(data){
this.active = data;
},
INFO(data){
Object.assign(this.info,data);
},
TOKEN(data){
this.token = data;
},
FirstGO(data){
this.firstGo = data;
}
}
});
import { ElMessage } from 'element-plus'
import {useStore} from '@/store/modules/app';
import api from '@/api/methods/index';
import axios from "axios"
export default {
setStorage(key,value,expire=15552000){
localStorage.setItem(key,JSON.stringify({
value:value,
now:Date.now(),
expire:expire
}))
},
getStorage(key){
if (localStorage.getItem(key)){
let obj = this.isJsonString(localStorage.getItem(key))?JSON.parse(localStorage.getItem(key)):{value:null,now:0,
expire:0};
if(Date.now()>obj.now+obj.expire*1000){
return null;
}else{
return obj.value;
}
} else{
return null;
}
},
//判断是否是json字符串
isJsonString(str) {
try {
if (str === null) {
return false;
}
if (typeof JSON.parse(str) == "object") {
return true;
}
} catch (e) {}
return false;
},
//判断一个数据是否为空
isEmpty(str) {
if (Object.prototype.toString.call(str) === '[object Undefined]') { //空
return true
} else if (
Object.prototype.toString.call(str) === '[object String]' ||
Object.prototype.toString.call(str) === '[object Array]') { //字条串或数组
return str.length == 0 ? true : false
} else if (Object.prototype.toString.call(str) === '[object Object]') {
return JSON.stringify(str) == '{}' ? true : false
} else if (Object.prototype.toString.call(str) === '[object Number]') {
return str == NaN ? true : false
} else {
return true
}
},
//获取url参数
getUrlKey(name) {
return (
decodeURIComponent(
(new RegExp("[?|&]" + name + "=" + "([^&;]+?)(&|#|;|$)").exec(
location.href
) || [, ""])[1].replace(/\+/g, "%20")
) || null
);
},
//时间封装
dateFormat: {
//日期格式化
/**
* @param date 标准时间日期格式
* @param fmt 格式化格式
* @returns {string}
*/
format(date, fmt = 'YYYY-MM-DD HH:mm:ss') {
date = new Date(date).getTime();
date = new Date(date);
let o = {
'M+': date.getMonth() + 1,
'D+': date.getDate(),
'h+': date.getHours() % 12 === 0 ? 12 : date.getHours() % 12,
'H+': date.getHours(),
'm+': date.getMinutes(),
's+': date.getSeconds(),
'q+': Math.floor((date.getMonth() + 3) / 3),
'S': date.getMilliseconds()
};
let week = {
'0': '\u65e5',
'1': '\u4e00',
'2': '\u4e8c',
'3': '\u4e09',
'4': '\u56db',
'5': '\u4e94',
'6': '\u516d'
};
if (/(Y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
}
if (/(E+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? '\u661f\u671f' : '\u5468') : '') + week[date.getDay() + ''])
}
for (let k in o) {
if (new RegExp('(' + k + ')').test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
}
}
return fmt
},
//格式日期兼容苹果端日期获取
dateReplace(date) {
return date.replace(/\-/g, '/');
}
},
upload_file(fileList,callBack){
let uploadList=[];
for(let file of fileList){
this.dealFile(file,function (data) {
uploadList.push(data);
if(uploadList.length==fileList.length){
callBack(uploadList);
}
})
}
},
async dealFile(file,callBack){
const store = useStore();
if(file.type.indexOf('image')>=0){
let expire = sessionStorage.getItem('oss-expire');
if(Number(expire) < Date.now()/1000 + 3||!store.ossInfo.expire){
await this.getOssConfig();
}
let formData = new FormData();
let fileName = '',FILEURL='';
if (file.name != '') {
fileName = this.set_file_name(file.name);
}
FILEURL = store.ossInfo.dir + '/' + encodeURIComponent(fileName);
formData.append("key", FILEURL);
formData.append("policy", store.ossInfo.policy);
formData.append("OSSAccessKeyId", store.ossInfo.accessid);
formData.append("success_action_status", '200');
formData.append("signature", store.ossInfo.signature);
formData.append("file", file);
axios({
method: "post",
url: store.ossInfo.host,
data: formData,
headers: {
"Content-Type": "multipart/form-data"
},
//原生获取上传进度的事件
onUploadProgress:(progressEvent)=>{
let complete = (progressEvent.loaded / progressEvent.total * 100 | 0) + '%';
// console.log('上传 ' + complete);
ElMessage.closeAll();
ElMessage({
message:`上传中...${complete}`,
type:'info'
})
}
}).then((res)=>{
console.log('res',res);
if (res.status == 200){
let type=''
if(file.type.indexOf('image')!=-1){
type=1
}else if(file.type.indexOf('application')!=-1||file.type.indexOf('text')!=-1){
type=3
}else{
type=100
}
let params={
name:fileName,
url:"https:"+store.ossInfo.host+"/"+FILEURL,
type:type,
size:file.size,
ext:fileName.substring(fileName.lastIndexOf('.')),
object_name:FILEURL
};
callBack(params);
}
});
}else{
if(file.type.indexOf('image')==-1){
ElMessage({
message:`请上传正确的图片格式`,
type:'error'
});
}
}
},
set_file_name(filename) {
let pos = filename.lastIndexOf('.');
let suffix = '',
file = '';
if (pos != -1) {
suffix = filename.substring(pos);
file = filename.substring(0, pos).replace(/#/g, '0')
}
let random = Date.now() + "_" + this.random_string(10)+"_";
return random + suffix;
},
// 设置随机数
random_string(len) {
let lens = len || 32;
let chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
let maxPos = chars.length;
let pwd = '';
for (let i = 0; i < lens; i++) {
pwd += chars.charAt(Math.floor(Math.random() * maxPos));
}
return pwd;
},
getOssConfig() {
const store = useStore();
return api.getOssConfig().then((res)=>{
if(res.code==0){
store.oss_info(res.data);
sessionStorage.setItem('oss-expire',res.data.expire);
}
})
}
}
<template>
<div class="home">
<div class="top">
</div>
<div class="bottom">
</div>
</div>
</template>
<script>
import {reactive,toRefs,defineComponent,onMounted,computed} from 'vue'
import {useRouter} from "vue-router"
import {ElMessage} from "element-plus"
import api from "@/api/methods/index"
import myPublic from "@/utils/public"
import {useStore} from '@/store/modules/app';
export default defineComponent({
name: "home",
setup(props, ctx) {
const router = useRouter();
const store = useStore();
const state = reactive({
count:100,
now:myPublic.dateFormat.format(Date.now(), 'YYYY-MM-DD'),
list:[]
});
onMounted(()=>{
});
return {
...toRefs(state),
};
},
components:{
}
})
</script>
<style scoped lang="less">
.home{
height: 100vh;
display: flex;
flex-direction: column;
overflow: hidden;
.top{
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
.card{
flex-shrink: 0;
display: flex;
justify-content: space-around;
background-color: #fff;
border-radius: .08rem;
box-shadow: 0 0 .2rem rgba(0,0,0,.3);
margin: .6rem .25rem 0 .25rem;
padding: .2rem .1rem;
.card-one{
position: relative;
flex: 1;
display: flex;
align-items: center;
flex-direction: column;
.box{
position: relative;
display: flex;
justify-content: center;
.badge{
position: absolute;
top: -5%;
left: 85%;
color: #fff;
background-color: #ff5048;
padding:0 .01rem;
font-size: .14rem;
line-height: .24rem;
height:.24rem;
z-index: 1;
&:before{
content:'';
position: absolute;
top: 0;
left: -.11rem;
width: .12rem;
height: .24rem;
border-top-left-radius: 2em;
border-bottom-left-radius: 2em;
background-color: #ff5048;
z-index: 0;
}
&:after{
content:'';
position: absolute;
top: 0;
right: -.11rem;
width: .12rem;
height: .24rem;
border-top-right-radius: 2em;
border-bottom-right-radius: 2em;
background-color: #ff5048;
z-index: 0;
}
}
.card-img{
width: .6rem;
height: .6rem;
}
}
.card-name{
margin-top: .1rem;
font-size: .16rem;
}
}
}
.calendar{
flex-shrink: 0;
}
.list{
flex: 1;
background-color: #f2f5f7;
overflow-y: auto;
padding: .1rem .1rem 0 .1rem;
.list-one{
display: flex;
flex-direction: column;
border-radius: .04rem;
background-color: #fff;
margin-bottom:.1rem;
padding: .1rem;
.list-title{
width: 100%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
color: #333;
margin-bottom:.1rem;
font-size: .18rem;
font-weight: bolder;
}
.list-bottom{
display: flex;
align-items: center;
overflow: hidden;
.icon{
width: fit-content;
display: flex;
color: #b2b2b2;
margin-right: .1rem;
overflow: hidden;
span{
flex: 1;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
color: #666666;
margin-left: .05rem;
font-size: .14rem;
}
}
}
&:active{
opacity: .8;
}
}
}
}
.bottom{
flex-shrink: 0;
height: .5rem;
}
}
</style>
<template>
<router-view v-slot="{Component}">
<component :is="Component">
</component>
</router-view>
</template>
<script>
// @ is an alias to /src
export default {
name: 'index',
components: {}
}
</script>
const path = require("path");
const debug = process.env.NODE_ENV !== "production";
const webpack = require('webpack');
module.exports = {
// 部署应用时的根路径(默认'/'),也可用相对路径(存在使用限制)
publicPath:'/pc/',
// 构建输出目录
outputDir: "dist",
// 静态资源目录 (js, css, img, fonts)
assetsDir: "static",
// 运行时版本是否需要编译
runtimeCompiler: true,
// 默认babel-loader忽略mode_modules,这里可增加例外的依赖包名
transpileDependencies: [],
// 是否在构建生产包时生成 sourceMap 文件,false将提高构建速度
productionSourceMap: true,
configureWebpack: config => { // webpack配置,值位对象时会合并配置,为方法时会改写配置
if (debug) { // 开发环境配置
config.devtool = "cheap-module-eval-source-map";
} else { // 生产环境配置
}
Object.assign(config, { // 开发生产共同配置,配置别名
resolve: {
extensions: [".js", ".vue", ".json"],
alias: {
"@": path.resolve(__dirname, "./src")
}
},
externals: {
}
});
},
// 构建时开启多进程处理babel编译
parallel: require("os").cpus().length > 1,
pages: {
index: {
// page 的入口
entry: 'src/main.js',
// 模板来源
template: 'public/index.html',
// 在 dist/index.html 的输出
filename: 'index.html',
// 当使用 title 选项时,
// template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
title: '',
// 在这个页面中包含的块,默认情况下会包含
// 提取出来的通用 chunk 和 vendor chunk。
chunks: ['chunk-vendors', 'chunk-common', 'index']
}
},
devServer:{
open:true,
// proxy: {
// '/phone_html/phone': {
// target: 'http://127.0.0.1:14101/phone',
// changeOrigin: true,
// pathRewrite: {
// // '^/apis': ''表示把/apis替换为‘’(空字符串),这样既能使用代理,
// // 又能在请求接口api时去掉/apis,获得正确的短信api路径。
// '^/phone_html/phone': ''
// },
// }
// }
}
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment