Commit 5977ce38 by zhuxiaomei

项目初始化

parents
NODE_ENV=development
VUE_APP_BASE_URL=http://api.dev.patzn.com:7000
NODE_ENV=production
VUE_APP_BASE_URL=http://api.patzn.com
NODE_ENV=test
VUE_APP_BASE_URL=http://api.pertest.patzn.com
.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?
# my-app
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Run your tests
```
npm run test
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "my-app",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve --mode development",
"build": "vue-cli-service build --mode production",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.20.0",
"core-js": "^3.6.5",
"dateformat": "^3.0.3",
"vant": "^2.10.9",
"vue": "^2.6.11",
"vue-navigation": "^1.1.4",
"vue-router": "^3.4.6",
"vue2-touch-events": "^2.3.2",
"vuex": "^3.5.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.5.0",
"@vue/cli-plugin-eslint": "^4.5.0",
"@vue/cli-service": "^4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"less": "^3.12.2",
"less-loader": "^7.0.2",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"globals": {
"BMap": true
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
<!DOCTYPE html>
<html lang="en">
<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, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover"
/>
<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>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</style>
/**
* 系统相关
*/
import http from '../http'
export default {
//意见反馈
advise: data => http.post('/base/v1/advise/', data).then(res => res),
}
/**
* 系统相关
*/
import http from '../http'
import Global from '../config'
export default {
//检测版本,自动更新
version: data => http.post('/base/v1/app_version/' + data.name + '_' + data.device + '?version=' + Global.version()).then(res => res),
}
/**
* 城市
*/
import http from '../http'
export default {
// 地址
list: () => http.post('/base/v1/country/list').then(res => res)
}
/**
* 系统相关
*/
import http from '../http'
export default {
//获取邮箱验证码
getEmailCode: data => http.post('/base/v1/email/send/', data).then(res => res),
//绑定邮箱
bindEmail: data => http.post('/base/v1/email/bind_' + data.code).then(res => res),
}
/**
* 系统相关
*/
import http from '../http'
export default {
submitExperience: data => http.post('/base/v1/experience/' + data.code, data).then(res => res),
}
/**
* 报告模板
*/
import http from '../http'
export default {
page: data => http.post('/base/v1/file_template/page', data).then(res => res)
}
/**
* 工作流相关
*/
import http from '../http'
export default {
//任务
listTask: data => http.post('/base/v1/flow_process/list_task', data).then(res => res),
//认领
claimTask: data => http.post('/base/v1/flow_process/claim_task/' + data).then(res => res),
fromKey: data => http.post('/base/v1/flow_process/fromKey', {taskId: data}).then(res => res),
}
/**
* 系统相关
*/
import http from '../http'
export default {
appMenu: data => http.post('/base/v1/resource/app_menu', data).then(res => res),
}
/**
* 系统相关
*/
import http from '../http'
export default {
getCode: data => http.post('/base/v1/sms/send_' + data.module + '/' + data.mobile).then(res => res),
//修改手机号
changeBindMobile: data => http.post('/base/v1/sms/change_bind_' + data).then(res => res),
}
/**
* sso
*/
import http from '../http'
export default {
//登录
login: data => http.post('/base/v1/sso/app_login', data).then(res => res),
//验证码登录
loginByCode: data => http.post('/base/v1/sso/ajax_login_back', data).then(res => res),
//注册
register: data => http.post('/base/v1/sso/register', data).then(res => res),
//修改密码
changPwd: data => http.post('/base/v1/sso/change_password', data).then(res => res),
//退出
logout: () => http.get('/base/v1/sso/logout').then(res => res),
}
/**
* 系统相关
*/
import http from '../http'
import httpJson from '../httpJson'
export default {
//个人模块-save
userRelResourceAdd: data => httpJson.post('/base/v1/user_rel_resource/', JSON.stringify(data)).then(res => res),
//个人模块-list
userRelResource: () => http.post('/base/v1/user_rel_resource/my_list').then(res => res),
}
/**
* 系统相关
*/
import http from '../http'
export default {
//用户修改密码
editPsd: data => http.put('/base/v1/user/password', data).then(res => res),
//获取用户信息
getUserInfo: () => http.get('/base/v1/user/info').then(res => res),
userEdit: data => http.put('/base/v1/user/' + data.id, data.obj).then(res => res),
// 人员查询
orginTreeList: () => http.post('/base/v1/org/org_tree').then(res => res),
userSelect: data => http.post('/base/v1/user/list_org/' + data.orgId).then(res => res),
userSelectByKeyword: data => http.post('/base/v1/user/list?realname=' + data).then(res => res),
}
/**
* 全局相关配置
*/
// 对外暴露全局常量及函数
export default {
//localStorage
setLogin: function (user) {
localStorage.setItem('fLoginUser', JSON.stringify(user));
},
//clear
logout: function () {
localStorage.removeItem('fLoginUser');
localStorage.removeItem('accessToken');
},
getLogin: function () {
return JSON.parse(localStorage.getItem('fLoginUser'));
},
//token
setToken: function (data) {
localStorage.setItem('accessToken', data);
},
//获取token
getToken: function () {
return localStorage.getItem('accessToken');
},
baseURL: process.env.VUE_APP_BASE_URL,
//version
version: function () {
return '0.0.0'
},
}
/**
* 抽样计划表相关
*/
import http from '../http'
export default {
page: data => http.post('/drs/v1/sampling_plan/page', data).then(res => res),
getById: id => http.get('/drs/v1/sampling_plan/' + id).then(res => res),
}
/**
* HTTP 请求 axios 封装
*/
import Qs from "qs";
import axios from 'axios'
import global from './config'
import loading from './loading'
// Axios 全局配置
const http = axios.create()
http.defaults.baseURL = process.env.VUE_APP_BASE_URL
http.defaults.withCredentials = true
// 添加请求拦截器
http.interceptors.request.use(
config => {
let tk = localStorage.getItem('accessToken');
if (tk) {
config.headers = {
'Content-Type': 'application/x-www-form-urlencoded'
};
config.headers.accessToken = tk;
}
config.transformRequest = [
// 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
function (data) {
return Qs.stringify(data);
}
]
return config
},
error => {
return Promise.reject(error)
}
)
// 返回数据处理
// 返回格式 {code:业务码 , data: 内容 , msg: 描述}
http.interceptors.response.use(
response => {
switch (response.data.code) {
case '-2':
global.logout()
// location.reload()
break
case '1':
return response.data.data
default:
loading.toast.show(response.data.code, response.data.msg)
}
},
error => {
return Promise.reject(error)
}
)
export default http
/**
* HTTP 请求 axios dto封装
*/
import axios from 'axios'
import global from './config'
import loading from './loading'
// Axios 全局配置
const httpJson = axios.create()
httpJson.defaults.baseURL = process.env.VUE_APP_BASE_URL
httpJson.defaults.withCredentials = true
// 添加请求拦截器
httpJson.interceptors.request.use(
config => {
let tk = localStorage.getItem('accessToken');
if (tk) {
config.headers = {
'Content-Type': 'application/json'
};
config.headers.accessToken = tk;
}
return config
},
error => {
return Promise.reject(error)
}
)
// 返回数据处理
// 返回格式 {code:业务码 , data: 内容 , msg: 描述}
httpJson.interceptors.response.use(
response => {
switch (response.data.code) {
case '-2':
global.logout()
location.reload();
break
case '1':
return response.data.data
default:
loading.toast.show(response.data.code, response.data.msg)
}
},
error => {
if (error.response.status === 401) {
console.log('unauthorized, logging out ...')
}
return Promise.reject(error)
}
)
export default httpJson
/**
* base
*/
export {default as sso} from './base/sso'
// export {default as resource} from './base/resource'
// export {default as userRelResource} from './base/user-rel-resource'
export {default as sysUser} from './base/user'
// export {default as appVersion} from './base/app-version'
// export {default as flowProcess} from './base/flow-process'
// export {default as email} from './base/email'
export {default as sms} from './base/sms'
export {default as advise} from './base/advise'
// export {default as country} from './base/country'
// export {default as fileTemplate} from './base/file-template'
/**
* res
*/
// export {default as customer} from './res/customer'
// export {default as dict} from './res/dict'
// export {default as serviceType} from './res/service-type'
// export {default as car} from './res/car'
/**
* message
*/
export {default as message} from './message/message'
/**
* drs
*/
export {default as samplingPlan} from './drs/sampling-plan'
/**
* 加载
*/
import Vue from 'vue'
function toasts(message) {
/*todo 请求接口之后的反馈*/
console.log(message, Vue)
}
var toast = {
show: function (type, message) {
console.log('===message==' + message);
var finalMessage = message;
if (!finalMessage) {
switch (type) {
case 1000:
finalMessage = '没有权限';
break;
case -201:
finalMessage = '没有用户';
break;
case -1:
finalMessage = '没有权限';
break;
case 500:
finalMessage = '网络错误';
break;
default:
finalMessage = '网络错误';
break;
}
finalMessage += type;
}
if (message === 'inactivate') {
//未激活状态
localStorage.setItem('inactivate', message);
} else {
toasts(finalMessage);
}
},
// showMessage: function (message) {
// toasts(message);
// },
//
// showLoading: function (show) {
// if (show) {
// // iView.LoadingBar.start();
// } else {
// // iView.LoadingBar.finish();
// }
// }
};
export default {
toast
}
/**
* 系统消息表相关
*/
import http from '../http'
export default {
deleteByIds: ids => http.delete('/message/v1/message/?ids=' + ids).then(res => res),
getById: id => http.get('/message/v1/message/' + id).then(res => res),
myPage: data => http.post('/message/v1/message/page_my', data).then(res => res),
read: ids => http.post('/message/v1/message/read?relIds=' + ids).then(res => res),
}
/**
* 资源-客户
*/
import http from '../http'
export default {
//客户
list: data => http.get('/res/v1/customer/list?cname=' + data).then(res => res)
}
/**
* 资源-字典
*/
import http from '../http'
export default {
// 多个字典查询
listDict: data => http.post('/res/v1/dict/list_dict', {'classTypeList': data.join(',')}).then(res => res),
// 单个字典查询
getItem: data => http.get('/res/v1/dict/dict_class_item?classType=' + data).then(res => res)
}
/**
* 资源-服务类型
*/
import http from '../http'
export default {
list: data => {
let obj = ''
if (data) {
obj = http.get('/res/v1/service_type/list?name=' + data).then(res => res)
} else {
obj = http.get('/res/v1/service_type/list', data).then(res => res)
}
return obj
}
}
/**
* 资源-用户编组
*/
import http from '../http'
export default {
//用户编组
userGroupList: () => http.post('/res/v1/user_group/list').then(res => res),
//编组关联用户(默认500条)
groupUserPage: data => http.post('/res/v1/user_group/page_rel_user', data).then(res => res),
}
<template>
<van-popup v-model="showPopup" round :style="{ width:'75%'}">
<div>
{{title}}
</div>
<div style="margin: 20px 10px">
<slot></slot>
</div>
<div>
<van-button type="primary" @click="onCancel">取消</van-button>
<van-button type="info" @click="onConfirm">确定</van-button>
</div>
</van-popup>
</template>
<script>
export default {
name: "ConfirmDialog",
props: {
title: String,
},
data() {
return {
showPopup: true
}
},
methods: {
onCancel() {
this.$emit('close')
},
onConfirm() {
this.$emit('confirm')
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<!--https://youzan.github.io/vant/#/zh-CN/form#biao-dan-xiang-lei-xing---shi-jian-xuan-ze-qi-->
<van-field
readonly
clickable
v-model="dateValue"
:label="label"
:placeholder="'点击选择'+label"
@click="showPicker = true"
></van-field>
<van-popup v-model="showPicker" position="bottom"
:safe-area-inset-bottom="true"
:close-on-popstate="true">
<van-datetime-picker
:type="type"
v-model="currentDate"
@confirm="onConfirm"
@cancel="showPicker = false"
></van-datetime-picker>
</van-popup>
</div>
</template>
<script>
export default {
name: "DateTimeField",
props: {
label: String,
value: {type: String, default: ''}, //默认值
type: {type: String, default: 'date'},
format: {type: String, default: 'yyyy-mm-dd'}
},
data() {
return {
showPicker: false,
currentDate: new Date()
}
},
computed: {
dateValue: {
get() {
return this.value
},
set(val) {
this.$emit('input', val)
}
}
},
watch: {
showPicker: function (newVal) {
if (newVal) {
this.currentDate = new Date()
}
}
},
methods: {
onConfirm(date) {
this.dateValue = this.$dateformat(date, this.format)
this.showPicker = false
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<datetime-field label="计划日期" v-model="planDate"></datetime-field>
<van-button type="info" @click="_clear">
清空
</van-button>
</div>
</template>
<script>
import DatetimeField from './DatetimeField'
export default {
name: "Search",
components: {
DatetimeField
},
data() {
return {
planDate: ''
}
},
methods: {
_clear() {
this.planDate = ''
}
}
}
</script>
<style scoped>
</style>
<template>
<div class="field-box">
<div class="label">
<span>抽样单编号</span>
</div>
<div class="value">
<input class="van-field__control cus-input-class">
</div>
</div>
</template>
<script>
/**
*自定义 Field
*/
export default {
name: "FieldCustomer"
}
</script>
<style lang="less" scoped>
.field-box {
width: 100%;
height: 100%;
display: flex;
.label {
width: 50%;
display: flex;
vertical-align: middle;
align-items: center;
justify-content: center;
}
.value {
flex: 1;
vertical-align: middle;
}
.cus-input-class {
height: 100%;
padding-left: 12px;
}
}
</style>
<template>
<!--https://youzan.github.io/vant/#/zh-CN/tabbar-->
<van-tabbar route fixed>
<van-tabbar-item replace to="/home" icon="home-o">
首页
</van-tabbar-item>
<van-tabbar-item replace to="/mine/mine" icon="friends-o">
个人中心
</van-tabbar-item>
</van-tabbar>
</template>
<script>
export default {
name: "FooterBar"
}
</script>
<style scoped>
</style>
<template>
<!--https://youzan.github.io/vant/#/zh-CN/search-->
<div class="search-bar-box">
<van-search
v-model="searchValue"
show-action
:placeholder="'请输入搜索'+labelText"
@search="onSearch"
>
<template #action>
<div @click="onSearch">搜索</div>
</template>
</van-search>
<div @click="showHighSearch = true" v-if="highSearch" class="high-search-text">高级查询</div>
<div class="high-search-cont" v-if="showHighSearch">
<van-nav-bar title="高级搜索"
:left-arrow="true"
@click-left="showHighSearch=false"></van-nav-bar>
<slot name="highSearch"></slot>
<div class="btn-box">
<van-button block type="info" @click="onHighSearch">搜索</van-button>
<van-button block type="default" @click="onReset" style="margin-top: 10px">清空</van-button>
</div>
</div>
</div>
</template>
<script>
export default {
name: "SearchBar",
props: {
label: String,
//是否展示高级查询按钮
highSearch: {type: Boolean, default: false}
},
data() {
return {
showHighSearch: false,
searchValue: '',
labelText: this.label ? this.label : '关键字'
}
},
methods: {
onSearch() {
this.$emit('search', this.searchValue)
},
onHighSearch() {
this.showHighSearch = false
this.searchValue = ''
this.$emit('high-search')
},
onReset() {
this.$emit('clear-high')
}
}
}
</script>
<style scoped>
</style>
/**
* 配置文件
*/
export default {
service:'double-sampling',
webURL: process.env.process.env.VUE_APP_WEB_URL,
baseURL: process.env.process.env.VUE_APP_BASE_URL,
ssoURL: process.env.process.env.VUE_APP_SSO_URL,
}
<template>
<div>
<slot name="navBar"></slot>
<div class="main-layout-cont">
<div>
<slot name="content"></slot>
</div>
</div>
<!--其他使用的组件等-->
<slot></slot>
</div>
</template>
<script>
/**
* 自定义标题栏布局
*/
export default {
name: "NavBarLayout"
}
</script>
<style scoped>
</style>
// 加载百度地图js
const map = {
init: function () {
const AK = '7aLLv8GDWaDFLiBlCrctGnq3vTFsHEWf'
const BMapURL = 'http://api.map.baidu.com/api?v=2.0' + AK + '&s=1&callback=onBMapCallback'
return new Promise((resolve) => {
// 如果已加载直接返回
if (typeof BMap !== 'undefined') {
resolve(BMap)
return true
}
// 百度地图异步加载回调处理
window.onBMapCallback = function () {
// console.log('百度地图脚本初始化成功...')
resolve(BMap)
};
// 插入script脚本
let scriptNode = document.createElement('script')
scriptNode.setAttribute('type', 'text/javascript')
scriptNode.setAttribute('src', BMapURL)
document.body.appendChild(scriptNode)
})
}
}
export default map
import dateformat from 'dateformat';
import global from '../api/config';
export default {
install(Vue) {
/**
* 日期格式化
* https://www.npmjs.com/package/dateformat
*/
Vue.prototype.$dateformat = function (date, format) {
return date ? dateformat(date, format) : ''
};
/**
* 重置数据
* */
Vue.prototype.$resetFields = function (formObj) {
let newFormObj = {}
for (let key in formObj) {
newFormObj[key] = ''
}
return newFormObj;
};
/**
* 序列化formObj 只返回有值的
* @param formObj
*/
Vue.prototype.$serializeForm = function (formObj) {
const newFormObj = {}
for (const key in formObj) {
// 不为空的时候传值
if (formObj[key] !== '') {
newFormObj[key] = formObj[key]
}
}
return newFormObj
}
/**
* 全局的配置
* @type {{getLogin, logout, baseURL, setToken, setLogin, getToken, version}}
*/
Vue.prototype.$global = global
},
}
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import plugins from './lib/plugins'
Vue.use(plugins)
// import Navigation from 'vue-navigation'
// Vue.use(Navigation, {router});
import Vue2TouchEvents from 'vue2-touch-events'
Vue.use(Vue2TouchEvents)
import Vant from 'vant';
import 'vant/lib/index.css';
Vue.use(Vant);
import '@/styles/main.less'
import SearchBar from '@/components/SearchBar.vue'
import DatetimeField from '@/components/DatetimeField.vue'
import ConfirmDialog from '@/components/ConfirmDialog.vue'
import CustomerNavBarLayout from '@/layout/CustomerNavBarLayout.vue'
Vue.component('search-bar', SearchBar)
Vue.component('datetime-field', DatetimeField)
Vue.component('confirm-dialog', ConfirmDialog)
Vue.component('customer-navBar-layout', CustomerNavBarLayout)
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app')
<template>
<div class="login-cont">
<div class="login-main login-main-forget">
<div class="logo-text">
<img src="@/assets/forgetPwd.png" height="40">
</div>
<van-form @submit="onSubmit">
<div class="field-input">
<van-field
v-model="formObj.mobile"
:left-icon="require('../assets/user.png')"
label-width="4.2em"
name="mobile"
label="手机号"
placeholder="请输入您的手机号"
clearable
:rules="[{ required: true, message: '' }]"
></van-field>
</div>
<div class="field-input">
<van-field
v-model="formObj.code"
center
:left-icon="require('../assets/code.png')"
label-width="4.2em"
name="code"
label="验证码"
placeholder="请输入验证码"
:rules="[{ required: true, message: '' }]">
<template #button>
<!--native-type="button" 阻止触发表单提交-->
<van-button size="small" type="info" native-type="button" @click="_getCode">
发送验证码
</van-button>
</template>
</van-field>
</div>
<div class="field-input">
<van-field
v-model="formObj.password"
:left-icon="require('../assets/psd.png')"
label-width="4.2em"
type="password"
name="password"
label="新密码"
placeholder="请输入新密码"
clearable
:rules="[{ required: true, message: '' }]"
></van-field>
</div>
<div class="field-input">
<van-field
v-model="confirmPwd"
:left-icon="require('../assets/psd.png')"
label-width="4.2em"
type="password"
name="confirmPwd"
label="确认密码"
placeholder="请确认密码"
clearable
:rules="[{ required: true, message: '' }]"
></van-field>
</div>
<div class="btn-box" style="margin-top: 30px">
<van-button block type="info" native-type="submit">
确认并登录
</van-button>
</div>
</van-form>
</div>
</div>
</template>
<script>
import {sms, sso} from '@/api'
export default {
name: "ForgetPwd",
data() {
return {
confirmPwd: '',
formObj: {
mobile: '',
password: '',
code: ''
},
}
},
methods: {
_getCode: async function () {
if (this.formObj.mobile === '') {
this.$toast('请输入手机号');
} else {
if (!/^((1[3,5,8][0-9])|(14[5,7])|(17[0,6,7,8])|(19[7]))\d{8}$/.test(this.formObj.mobile)) {
this.$toast('手机号格式不正确');
} else {
let result = await sms.getCode({
module: 'changePasswordByMobile',
mobile: this.formObj.mobile
})
if (result) {
this.$toast.success('发送成功!');
}
}
}
},
onSubmit() {
if (this.formObj.password !== this.confirmPwd) {
this.$toast('两次填写的密码不一致');
} else {
this._save()
}
},
_save: async function () {
let result = await sso.changPwd(this.formObj)
if (result) {
this.$toast.success('密码修改成功!');
setTimeout(() => {
this._toLogin();
}, 1000)
}
},
//跳到注册界面
_toLogin() {
// this.$navigation.cleanRoutes();
this.$router.replace('/login');
},
}
}
</script>
<style scoped>
</style>
<template>
<div>
<!--https://youzan.github.io/vant/#/zh-CN/grid-->
<div class="layout-cont home-cont">
<van-grid :gutter="10" :column-num="3" :icon-size="40">
<!--1、icon参数引入使用,否则不显示-->
<van-grid-item v-for="item in menuList" :key="item.title" :icon="item.img"
:text="item.title" @click="_goto(item)"></van-grid-item>
<!--2、require使用 详见:https://youzan.github.io/vant/#/zh-CN/image#chang-jian-wen-ti-->
<!--<van-grid-item v-for="item in menuList" :key="item.title" :icon="require('../assets/index/1.png')"-->
<!--:text="item.title" ></van-grid-item>-->
<!--3、使用该组件的icon插槽 详见:https://youzan.github.io/vant/#/zh-CN/grid#api-->
</van-grid>
</div>
<FooterBar></FooterBar>
</div>
</template>
<script>
import indexImg10 from '../assets/index/10.png'
import indexImg1 from '../assets/index/1.png'
import indexImg11 from '../assets/index/11.png'
import FooterBar from '@/components/FooterBar.vue'
export default {
name: "Home",
components: {
FooterBar
},
data() {
return {
menuList: [
{img: indexImg10, title: '抽样任务', uri: '/sampling_task/sampling_task'},
{img: indexImg1, title: '抽样单管理', uri: '/sampling_list/sampling_task'},
{img: indexImg11, title: '历史抽样单', uri: '/history_sampling/sampling_list'},
],
}
},
methods: {
_goto(item) {
this.$router.push(item.uri)
}
}
}
</script>
<style scoped>
</style>
<template>
<div class="main-content-con">
<!--https://youzan.github.io/vant/#/zh-CN/nav-bar-->
<van-nav-bar :title="$route.meta.title"
:left-arrow="$route.meta.leftArrow!==false"
v-if="$route.meta.hideNavBar!==true"
@click-left="_back"></van-nav-bar>
<div class="main-layout-cont" :class="[{'main-layout-cont-hide-navbar':$route.meta.hideNavBar===true}]">
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
name: "Index",
components: {},
methods: {
_back() {
this.$router.go(-1)
}
}
}
</script>
<style scoped>
</style>
<template>
<div class="login-cont">
<div class="login-main">
<h1>欢迎登录</h1>
<van-form @submit="onSubmit">
<div class="field-input">
<van-field
v-model="formObj.username"
:left-icon="require('../assets/user.png')"
label-width="4.2em"
name="username"
label="用户名"
placeholder="请填写用户名"
clearable
:rules="[{ required: true, message: '' }]"
></van-field>
</div>
<div class="field-input">
<!--todo form表单回车提交-->
<van-field
v-model="formObj.password"
:left-icon="require('../assets/psd.png')"
label-width="4.2em"
type="password"
name="password"
label="密码"
placeholder="请填写密码"
clearable
:rules="[{ required: true, message: '' }]"
></van-field>
</div>
<div class="forget-text">
<div>
<van-checkbox shape="square" v-model="checked" icon-size="18px">记住密码</van-checkbox>
</div>
<div @click="_forgetPwd">忘记密码?</div>
</div>
<div class="btn-box">
<van-button block type="info" native-type="submit">
立即登录
</van-button>
</div>
</van-form>
</div>
<confirm-dialog v-if="showPopup" title="请输入您的新密码" @confirm="_toLogin" @close="showPopup=false">
<van-field v-model="formObj.newPwd" label="密码" placeholder="请输入您的新密码"></van-field>
</confirm-dialog>
</div>
</template>
<script>
import {sso, sysUser} from '../api'
export default {
name: "Login",
data() {
return {
formObj: {
username: '',
password: '',
newPwd: ''
},
checked: false,
showPopup: false
}
},
mounted() {
this._inactivate()
},
methods: {
onSubmit(res) {
console.log(res, 'login-info')
this._login(res)
},
_login: async function (res) {
let token = await sso.login(res)
if (token) {
this.$global.setToken(token)
if (this.checked) {
localStorage.setItem('username', this.formObj.username);
if (localStorage.getItem('inactivate')) {
//第一次激活后保存密码
localStorage.setItem('password', this.formObj.newPwd);
} else {
//已经激活状态保存密码
localStorage.setItem('password', this.formObj.password);
}
} else {
localStorage.removeItem('username');
localStorage.removeItem('password');
}
this._getUserInfo();
} else {
//激活
this._inactivate();
}
},
//获取用户信息
async _getUserInfo() {
let user = await sysUser.getUserInfo();
if (user) {
this.$global.setLogin(user);
this.$router.replace('/home');
//todo 清空路由 报错问题 需要降低vue-router版本
// this.$navigation.cleanRoutes();
}
},
_forgetPwd() {
this.$router.push('/forget_pwd')
},
//激活
_inactivate() {
if (localStorage.getItem('inactivate') === 'inactivate') {
this.formObj.newPwd = ''
this.showPopup = true
}
},
_toLogin() {
if (this.formObj.newPwd === '') {
this.$toast('请输入新密码!');
return
}
let data = {
username: this.formObj.username,
password: this.formObj.newPwd
}
this._login(data)
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<search-bar label="计划名称"
highSearch
@search="_search"
@high-search="_highSearch"
@clear-high="_clearHigh">
<template #highSearch>
<van-field v-model="formObj.name" label="抽样单编号" placeholder="请输入抽样单编号"></van-field>
<datetime-field label="抽样日期" v-model="formObj.planDate"></datetime-field>
<van-field v-model="formObj.name" label="任务名称" placeholder="请输入任务名称"></van-field>
<van-field v-model="formObj.name" label="被抽样单位" placeholder="请输入被抽样单位名称"></van-field>
</template>
</search-bar>
<div class="layout-cont-sh">
<van-list
v-model="loading"
:finished="finished"
finished-text="没有更多了"
@load="onLoad">
<van-swipe-cell v-for="item in resultList" :key="item.name">
<div class="result-item" @click="_goto(item)">
<div>抽样单编号:</div>
<div>抽样日期:</div>
<div>任务名称:</div>
<div>任务编号:</div>
<div>生产名称:</div>
<div>样品名称:</div>
<div>被抽样单位名称:</div>
</div>
</van-swipe-cell>
</van-list>
</div>
</div>
</template>
<script>
export default {
name: "SamplingList",
data() {
return {
formObj: {
name: '',
planDate: '',
uname: '',
ctime: ''
},
resultList: [
{name: '计划名称', status: 1},
{name: '计划名称2', status: 2}, {name: '计划名称', status: 1},
{name: '计划名称2', status: 2}, {name: '计划名称', status: 1},
{name: '计划名称2', status: 2}, {name: '计划名称', status: 1},
{name: '计划名称2', status: 2}, {name: '计划名称', status: 1},
{name: '计划名称2', status: 2}, {name: '计划名称', status: 1},
{name: '计划名称2', status: 2}, {name: '计划名称', status: 1},
{name: '计划名称2', status: 2},
]
}
},
methods: {
_search(value) {
this.formObj = this.$resetFields(this.formObj)
console.log('search', value)
},
_highSearch() {
console.log('high-search')
console.log(this.formObj, 'formObj')
},
_clearHigh() {
this.formObj = this.$resetFields(this.formObj)
console.log(this.formObj, 123)
},
_goto(){
this.$router.push('/sampling_list/sampling_list_detail')
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
<van-field
v-model="content"
rows="5"
autosize
label="留言"
label-width="50px"
type="textarea"
maxlength="200"
placeholder="请输入您的宝贵建议与意见(200字以内)"
show-word-limit
></van-field>
<div style="height: 44px;width: 80%;margin: 20px auto 0">
<van-button block type="info" @click="_ok">保存</van-button>
</div>
</div>
</template>
<script>
import {advise} from '../../api'
export default {
name: "FeedBack",
data() {
return {
content: ''
}
},
methods: {
async _ok() {
if (this.content === '') {
this.$toast('请输入内容');
} else {
let result = await advise.advise({content: this.content})
if (result) {
this.content = '';
this.$toast.success('提交成功!您的意见我们会慎重考虑!')
setTimeout(() => {
this.$router.go(-1)
}, 2000)
}
}
}
}
}
</script>
<style scoped>
</style>
<template>
<div class="personal-cont">
<div class="layout-cont">
<div class="personal-top-img">
<img src="@/assets/touxiang2.png" @click="_goto">
</div>
<div>
<van-cell-group>
<van-cell title="账号信息" icon="user-o" is-link to="/mine/user_info"></van-cell>
</van-cell-group>
</div>
<div style="margin-top: 10px">
<van-cell-group>
<van-cell title="服务热线:0532-67760070 / 13335043671" icon="phone-o"></van-cell>
</van-cell-group>
</div>
<div style="margin-top: 10px">
<van-cell-group>
<van-cell title="意见反馈" icon="edit" is-link to="/mine/feed_back"></van-cell>
</van-cell-group>
</div>
<div style="margin: 20px 20px 0">
<van-button block type="info" @click="_exit">
安全退出当前账户
</van-button>
</div>
</div>
<FooterBar></FooterBar>
</div>
</template>
<script>
import FooterBar from '@/components/FooterBar.vue'
export default {
name: "Mine",
components:{
FooterBar
},
methods: {
_goto() {
this.$router.push('/mine/user_info')
},
_exit() {
this.$global.logout();
// this.$navigation.cleanRoutes();
this.$router.replace('/login');
},
}
}
</script>
<style scoped>
</style>
<template>
<div>
<div style="margin-top: 20px">
<van-cell title="用户名" :value="userInfo.username"></van-cell>
<van-cell title="真实姓名" :value="userInfo.realname"></van-cell>
<van-cell title="性别" :value="userInfo.sex"></van-cell>
</div>
<div style="margin-top: 20px">
<van-cell title="所属部门" :value="userInfo.orgNames"></van-cell>
<van-cell title="所属角色" :value="userInfo.roleNames"></van-cell>
</div>
<div style="margin-top: 20px">
<van-cell title="手机号" :value="userInfo.mobile"></van-cell>
<van-cell title="个人邮箱" :value="userInfo.email"></van-cell>
<van-cell title="联系QQ" :value="userInfo.qq"></van-cell>
</div>
<div style="margin: 40px auto 0;width: 80%;">
<van-button icon="edit" block type="info" @click="_editPwd">修改密码</van-button>
</div>
</div>
</template>
<script>
import {sysUser} from '../../api'
export default {
data() {
return {
userInfo: {},
id: '',
}
},
mounted() {
this._getUserInfo()
},
methods: {
//跳转
_editPwd() {
this.$router.push('/mine/pwd_edit');
},
//用户信息
async _getUserInfo() {
//重新获取用户信息
let user = await sysUser.getUserInfo();
if (user) {
this.$global.setLogin(user);
this.userInfo = user;
this.id = user.id;
}
},
//退出
_exit() {
this.$global.logout();
// this.$navigation.cleanRoutes(); //清空路由了,但是浏览器中的路由仍在
this.$router.replace('/login')
},
}
}
</script>
<style scoped>
.header-top-title {
margin: 65px auto 10px auto;
text-align: center;
}
</style>
<template>
<div>
<!--标题-->
<ToPBarNormal :title="title"></ToPBarNormal>
<!--提示信息-->
<div class="result-cont">
<p style="padding:10px;text-align: center">更改邮箱需要短信验证。</p>
<div class="phone_edit">
<group>
<x-input title="邮箱" v-model="email" placeholder="请输入邮箱" is-type="email"></x-input>
</group>
</div>
<div style="margin-top: 20px" class="login-exit" @click="_next">下一步</div>
</div>
</div>
</template>
<script>
import ToPBarNormal from '../../../components/topBar/TopBarNormal'
import {XInput, Group} from 'vux'
export default {
components: {
ToPBarNormal,
XInput,
Group,
},
data() {
return {
title: '邮箱',
email: ''
}
},
methods: {
//获取验证码
_next() {
if (this.email) {
let myReg = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/;
if (myReg.test(this.email)) {
this._ok();
} else {
this._msg('邮箱填写错误');
}
} else {
this._msg('请输入邮箱');
}
},
_ok() {
let data = {
email: this.email,
};
this.$store.dispatch('SystemManage/getEmailCode', data).then(() => {
if (this.$store.state.SystemManage.success) {
this.$router.push({path: '/sys/email_sms', query: {email: this.email}});
} else {
this._msg('验证码发送失败');
}
});
},
//提示
_msg(msg) {
this.$vux.toast.show({
type: 'text',
width: '10em',
text: msg,
time: 1000
});
},
}
}
</script>
<template>
<div>
<!--标题-->
<ToPBarNormal :title="title"></ToPBarNormal>
<!--提示信息-->
<div class="result-cont">
<p style="padding:10px">我们已经给您的邮箱<a> {{email}} </a>发送了一条验证码,请及时查看邮件。</p>
<div class="phone_edit">
<group>
<x-input placeholder="请输入验证码" v-model="code">
<span slot="right" v-show="selected" class="phone_vcode" @click="_getCode"><a>重新发送</a></span>
<span slot="right" v-show="!selected" class="phone_vcode">重新发送({{second}}s)</span>
</x-input>
</group>
</div>
<div style="margin-top: 20px;background: #ccc" class="login-exit" v-show="!code">完成</div>
<div style="margin-top: 20px" class="login-exit" @click="_ok" v-show="code">完成</div>
</div>
</div>
</template>
<script>
import ToPBarNormal from '../../../components/topBar/TopBarNormal'
import {XInput, Group} from 'vux'
export default {
components: {
ToPBarNormal,
XInput,
Group
},
data() {
return {
title: '请输入验证码',
code: '',
email: '',
second: 59,
selected: false,
id: '',
obj: {}
}
},
mounted() {
this._getQuery();
},
methods: {
_getQuery() {
this.email = this.$route.query.email;
this.obj = JSON.parse(localStorage.getItem('fLoginUser'));
this.id = this.obj.id;
this.selected = false;
this.second = 59;
this._count();
},
//提示
_msg(msg) {
this.$vux.toast.show({
type: 'text',
width: '10em',
text: msg,
time: 1000
});
},
//完成
_ok() {
this.$store.dispatch('SystemManage/bindEmail', {code: this.code}).then(() => {
if (this.$store.state.SystemManage.model) {
this._msg('修改成功');
this.$router.go(-2);
}
});
},
//发送验证码
_getCode() {
this.selected = false;
this.second = 59;
let data = {
email: this.email,
};
this.$store.dispatch('SystemManage/getEmailCode', data).then(() => {
if (this.$store.state.SystemManage.success) {
this._count();
} else {
this._msg('验证码发送失败');
}
});
},
//计数
_count() {
let second = this.second;
if (second === 0) {
this.selected = true;
this.second = 59;
return;
}
setTimeout(() => {
this.second = second - 1;
this._count();
}, 1000)
},
}
}
</script>
<template>
<div>
<!--标题-->
<ToPBarNormal :title="title"></ToPBarNormal>
<!--提示信息-->
<div class="result-cont">
<p style="padding:10px;text-align: center">更改手机号码需要短信验证。</p>
<div class="phone_edit">
<group>
<x-input title="+86" v-model="mobile" :max="11" is-type="china-mobile" keyboard="number"
placeholder="请输入手机号"></x-input>
</group>
</div>
<div style="margin-top: 20px" class="login-exit" @click="_next">下一步</div>
</div>
</div>
</template>
<script>
import ToPBarNormal from '../../../components/topBar/TopBarNormal'
import {XInput, Group} from 'vux'
export default {
components: {
ToPBarNormal,
XInput,
Group,
},
name: "phone-edit",
data() {
return {
title: '手机号码',
mobile: ''
}
},
methods: {
//获取验证码
_next() {
if (this.mobile) {
let myReg = /^1\d{10}$/;
if (myReg.test(this.mobile)) {
this._ok();
} else {
this._msg('号码填写错误');
}
} else {
this._msg('请输入手机号');
}
},
_ok() {
let data = {
mobile: this.mobile,
module: 'bindChangeMobile'
};
this.$store.dispatch('SystemManage/getCode', data).then(() => {
if (this.$store.state.SystemManage.model) {
this.$router.push({path: '/sys/sms', query: {mobile: this.mobile}});
} else {
this._msg('验证码发送失败');
}
});
},
//提示
_msg(msg) {
this.$vux.toast.show({
type: 'text',
width: '10em',
text: msg,
time: 1000
});
},
}
}
</script>
<template>
<div>
<!--标题-->
<ToPBarNormal :title="title"></ToPBarNormal>
<!--提示信息-->
<div class="result-cont">
<p style="padding:10px">我们已经给您的手机号<a> +86 {{mobile}} </a>发送了一条验证短信,请及时查看。</p>
<div class="phone_edit">
<group>
<x-input placeholder="请输入短信验证码" v-model="code">
<span slot="right" v-show="selected" class="phone_vcode" @click="_getCode"><a>重新发送</a></span>
<span slot="right" v-show="!selected" class="phone_vcode">重新发送({{second}}s)</span>
</x-input>
</group>
</div>
<div style="margin-top: 20px;background: #ccc" class="login-exit" v-show="!code">完成</div>
<div style="margin-top: 20px" class="login-exit" @click="_ok" v-show="code">完成</div>
</div>
</div>
</template>
<script>
import ToPBarNormal from '../../../components/topBar/TopBarNormal'
import {XInput, Group} from 'vux'
export default {
components: {
ToPBarNormal,
XInput,
Group
},
name: "sms",
data() {
return {
title: '请输入短信验证码',
code: '',
mobile: '',
second: 59,
selected: false
}
},
mounted() {
this._getQuery();
},
methods: {
_getQuery() {
this.mobile = this.$route.query.mobile;
this.selected = false;
this.second = 59;
this._count();
},
//提示
_msg(msg) {
this.$vux.toast.show({
type: 'text',
width: '10em',
text: msg,
time: 1000
});
},
//完成
_ok() {
this.$store.dispatch('SystemManage/changeBindMobile', this.code).then(() => {
if (this.$store.state.SystemManage.model) {
this._msg('修改成功');
this.$router.go(-2);
}
});
},
//发送验证码
_getCode() {
this.selected = false;
this.second = 59;
let data = {
mobile: this.mobile,
module: 'bindChangeMobile'
};
this.$store.dispatch('SystemManage/getCode', data).then(() => {
if (this.$store.state.SystemManage.model) {
this._count();
} else {
this._msg('验证码发送失败');
}
});
},
//计数
_count() {
let second = this.second;
if (second === 0) {
this.selected = true;
this.second = 59;
return;
}
setTimeout(() => {
this.second = second - 1;
this._count();
}, 1000)
},
}
}
</script>
<template>
<div>
<van-form @submit="onSubmit">
<div style="margin-top: 20px">
<van-field v-model="oldPwd" label="旧密码" placeholder="请输入旧密码"
:rules="[{ required: true, message: '' }]"></van-field>
</div>
<div style="margin-top: 20px">
<van-field v-model="newPwd" label="新密码" placeholder="请输入新密码"
:rules="[{ required: true, message: '' }]"></van-field>
</div>
<div style="margin-top: 20px">
<van-field v-model="newPwds" label="确认密码" placeholder="请确认密码"
:rules="[{ required: true, message: '' }]"></van-field>
</div>
<div style="margin: 40px 16px;">
<van-button block type="info" native-type="submit">
保存
</van-button>
</div>
</van-form>
</div>
</template>
<script>
import {sysUser} from '@/api'
export default {
name: "pwd-edit",
data() {
return {
title: '修改密码',
oldPwd: '',
newPwd: '',
newPwds: '',
}
},
methods: {
onSubmit() {
if (this.newPwds !== this.newPwd) {
this.$toast('两次填写的密码不一致');
} else {
this._save()
}
},
_save: async function () {
let data = {
oldPwd: this.oldPwd,
newPwd: this.newPwd
};
let result = await sysUser.editPsd(data)
if (result) {
let that = this;
this.$dialog.confirm({
title: '提示',
message: '登录密码已被修改,请重新登录!',
}).then(() => {
that._exit(); //退出重新登录
}).catch(() => {
// on cancel
});
}
},
//退出
_exit() {
this.$global.logout();
localStorage.removeItem('password'); //清空密码
// this.$navigation.cleanRoutes();
this.$router.replace('/login');
},
}
}
</script>
This diff is collapsed. Click to expand it.
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