26 changed files with 1184 additions and 241 deletions
After Width: | Height: | Size: 8.6 KiB |
@ -0,0 +1,48 @@ |
|||||
|
/** |
||||
|
* 设置粘贴板数据 |
||||
|
* @param {String} text 要设置的字符串 |
||||
|
* 如果未设置参数,则清空数据 |
||||
|
*/ |
||||
|
function setClipboardText(text) { |
||||
|
try { |
||||
|
var os = plus.os.name; |
||||
|
text = text || ''; |
||||
|
if ('iOS' == os) { |
||||
|
// var UIPasteboard = plus.ios.importClass('UIPasteboard');
|
||||
|
// var pasteboard = UIPasteboard.generalPasteboard();
|
||||
|
// pasteboard.setValueforPasteboardType(text, 'public.utf8-plain-text');
|
||||
|
var pasteboard = plus.ios.invoke('UIPasteboard', 'generalPasteboard'); |
||||
|
plus.ios.invoke(pasteboard, 'setValue:forPasteboardType:', text, 'public.utf8-plain-text'); |
||||
|
} else { |
||||
|
var main = plus.android.runtimeMainActivity(); |
||||
|
// var Context = plus.android.importClass('android.content.Context');
|
||||
|
// var clip = main.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
|
var clip = main.getSystemService('clipboard'); |
||||
|
plus.android.invoke(clip, 'setText', text); |
||||
|
} |
||||
|
} catch (e) { |
||||
|
console.error('error @setClipboardText!!'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
function getClipboardText() { |
||||
|
try { |
||||
|
var os = plus.os.name; |
||||
|
if ('iOS' == os) { |
||||
|
var pasteboard = plus.ios.invoke('UIPasteboard', 'generalPasteboard'); |
||||
|
return plus.ios.invoke(pasteboard, 'valueForPasteboardType:', 'public.utf8-plain-text') |
||||
|
} else { |
||||
|
var main = plus.android.runtimeMainActivity(); |
||||
|
var clip = main.getSystemService('clipboard'); |
||||
|
return plus.android.invoke(clip, 'getText'); |
||||
|
} |
||||
|
} catch (e) { |
||||
|
console.error('error @getClipboardText!!'); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
export default { |
||||
|
setClipboardText, |
||||
|
getClipboardText |
||||
|
} |
@ -0,0 +1,8 @@ |
|||||
|
// 默认主题文件 |
||||
|
.theme-default { |
||||
|
background-color: #333; |
||||
|
.u-card { |
||||
|
font-size: 24px !important; |
||||
|
color: #0f0; |
||||
|
} |
||||
|
} |
@ -0,0 +1,5 @@ |
|||||
|
// 整合所有主题 |
||||
|
|
||||
|
// 默认主题 |
||||
|
@import './default.scss'; |
||||
|
@import './test.scss'; |
@ -0,0 +1,8 @@ |
|||||
|
// TODO: 测试用的scss主题样式 |
||||
|
.theme-test { |
||||
|
background-color: #fff; |
||||
|
.u-card { |
||||
|
font-size: 24px !important; |
||||
|
background-color: #ff0 !important; |
||||
|
} |
||||
|
} |
@ -0,0 +1,13 @@ |
|||||
|
<template> |
||||
|
<view :class="[theme]"> |
||||
|
<slot></slot> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { computed } from 'vue'; |
||||
|
import { useStore } from 'vuex'; |
||||
|
|
||||
|
const store = useStore(); |
||||
|
const theme = computed(() => store.state.theme); |
||||
|
</script> |
@ -1,7 +0,0 @@ |
|||||
<!-- |
|
||||
* @Author: aBin |
|
||||
* @email: binbin0314@126.com |
|
||||
* @Date: 2021-07-19 15:40:02 |
|
||||
* @LastEditors: aBin |
|
||||
* @LastEditTime: 2021-07-19 15:40:03 |
|
||||
--> |
|
@ -0,0 +1,7 @@ |
|||||
|
import { computed } from 'vue'; |
||||
|
import { useStore } from 'vuex'; |
||||
|
export default function useTheme() { |
||||
|
const store = useStore(); |
||||
|
const theme = computed(() => store.state.theme); |
||||
|
return theme; |
||||
|
} |
@ -0,0 +1,285 @@ |
|||||
|
import { ref, computed } from 'vue'; |
||||
|
import { useStore } from 'vuex'; |
||||
|
import clipboard from "@/common/js/dc-clipboard/clipboard.js" |
||||
|
|
||||
|
export default function mixinInit { |
||||
|
const store = useStore(); |
||||
|
const user = computed(() => store.state.user.user); |
||||
|
const rules = ref({ |
||||
|
phone: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
message: '请输入手机号', |
||||
|
trigger: ['change','blur'], |
||||
|
}, |
||||
|
{ |
||||
|
validator: (rule, value, callback) => { |
||||
|
// 调用uView自带的js验证规则,详见:https://www.uviewui.com/js/test.html
|
||||
|
return this.$u.test.mobile(value); |
||||
|
}, |
||||
|
message: '手机号码不正确', |
||||
|
// 触发器可以同时用blur和change,二者之间用英文逗号隔开
|
||||
|
trigger: ['change','blur'], |
||||
|
} |
||||
|
], |
||||
|
verificationCodeValue: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
message: '请输入图形验证码', |
||||
|
trigger: ['change','blur'], |
||||
|
}, |
||||
|
{ |
||||
|
type: 'number', |
||||
|
message: '图形验证码只能为数字', |
||||
|
trigger: ['change','blur'], |
||||
|
} |
||||
|
], |
||||
|
smsCode: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
message: '请输入验证码', |
||||
|
trigger: ['change','blur'], |
||||
|
}, |
||||
|
{ |
||||
|
type: 'number', |
||||
|
message: '验证码只能为数字', |
||||
|
trigger: ['change','blur'], |
||||
|
} |
||||
|
], |
||||
|
account: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
message: '请输入用户名', |
||||
|
trigger: ['change','blur'], |
||||
|
}, |
||||
|
{ |
||||
|
min: 2, |
||||
|
max: 20, |
||||
|
message: '用户名长度在2到20个字符', |
||||
|
trigger: ['change','blur'], |
||||
|
}, |
||||
|
{ |
||||
|
pattern: /^[a-zA-Z0-9._-]{2,20}$/, |
||||
|
message: '请输入2-20位字母、数字、汉字或字符"_ - ."', |
||||
|
trigger: ['change','blur'], |
||||
|
} |
||||
|
], |
||||
|
password: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
message: '请输入密码', |
||||
|
trigger: ['change','blur'], |
||||
|
}, |
||||
|
{ |
||||
|
min: 6, |
||||
|
max: 20, |
||||
|
message: '密码长度在6到20个字符', |
||||
|
trigger: ['change','blur'], |
||||
|
}, |
||||
|
{ |
||||
|
// 正则不能含有两边的引号
|
||||
|
pattern: /^[a-zA-Z0-9._-]{6,20}$/, |
||||
|
message: '请输入6-20位字母、数字、汉字或字符"_ - ."', |
||||
|
trigger: ['change','blur'], |
||||
|
} |
||||
|
], |
||||
|
}); |
||||
|
const errorType = ref(['message']); |
||||
|
const labelPosition = ref('left'); |
||||
|
const border = ref(false); |
||||
|
const smsCode = ref(''); // 短信验证码
|
||||
|
const showInterval = ref(false); |
||||
|
const interval = ref(120); |
||||
|
const codeTimer = ref(null); |
||||
|
const showPaste = ref(false); |
||||
|
|
||||
|
// 获取图形验证码
|
||||
|
async function getImageCode() { |
||||
|
console.log('5555') |
||||
|
uni.$ui.showLoading(); |
||||
|
try { |
||||
|
const data = await uni.$u.api.getImageCode(); |
||||
|
const { imageBase64, verificationCodeId } = data; |
||||
|
imageBase64 = imageBase64 || ''; |
||||
|
verificationCodeId = verificationCodeId || ''; |
||||
|
uni.$ui.hideLoading(); |
||||
|
} catch (error) { |
||||
|
uni.$ui.hideLoading(); |
||||
|
uni.$ui.showToast(error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
// errorType,
|
||||
|
// rules,
|
||||
|
// labelPosition,
|
||||
|
// border,
|
||||
|
getImageCode, |
||||
|
// hasvalue,
|
||||
|
// getCode,
|
||||
|
// getCodeInterval,
|
||||
|
// checkRules,
|
||||
|
// setCode,
|
||||
|
// getClipboardContents,
|
||||
|
// verifyPhone,
|
||||
|
// verifyLoginname,
|
||||
|
// handleWxLogin
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
// const mixin = {
|
||||
|
// computed: mapState('user', ['user']),
|
||||
|
|
||||
|
// onReady() {
|
||||
|
// this.$refs.uForm.setRules(this.rules);
|
||||
|
// },
|
||||
|
|
||||
|
// methods: {
|
||||
|
// ...mapActions('user', ['sendCode']),
|
||||
|
|
||||
|
// 获取图形验证码
|
||||
|
// async getImageCode() {
|
||||
|
// this.$util.showLoading();
|
||||
|
// try {
|
||||
|
// const data = await uni.$u.api.getImageCode();
|
||||
|
// const { imageBase64, verificationCodeId } = data;
|
||||
|
// this.imageBase64 = imageBase64 || '';
|
||||
|
// this.verificationCodeId = verificationCodeId || '';
|
||||
|
// uni.hideLoading();
|
||||
|
// } catch (error) {
|
||||
|
// uni.hideLoading();
|
||||
|
// uni.$ui.showToast(error);
|
||||
|
// }
|
||||
|
// },
|
||||
|
|
||||
|
// //有图片验证码的值
|
||||
|
// hasvalue() {
|
||||
|
// if(this.model.smsCode || this.model.showPaste) return
|
||||
|
// if (!this.verifyPhone(this.model.phone)) {
|
||||
|
// uni.$ui.showToast('请输入正确的手机号');
|
||||
|
// return;
|
||||
|
// }
|
||||
|
// if (!this.model.verificationCodeValue) {
|
||||
|
// uni.$ui.showToast('请输入图形验证码');
|
||||
|
// return;
|
||||
|
// }
|
||||
|
// this.getCode();
|
||||
|
// },
|
||||
|
|
||||
|
// // 获取验证码
|
||||
|
// async getCode() {
|
||||
|
// try {
|
||||
|
// const { phone, verificationCodeValue } = this.model;
|
||||
|
// const { verificationCodeId } = this;
|
||||
|
|
||||
|
// if (!verificationCodeId || !verificationCodeValue) {
|
||||
|
// uni.$ui.showToast('缺少图形验证码参数');
|
||||
|
// return;
|
||||
|
// }
|
||||
|
// const params = {
|
||||
|
// phone,
|
||||
|
// verificationCodeId,
|
||||
|
// verificationCodeValue,
|
||||
|
// };
|
||||
|
// const date = await store.dispatch('user/sendCode', params);
|
||||
|
// getCodeInterval();
|
||||
|
// showPaste.value = true;
|
||||
|
// } catch (err) {
|
||||
|
// throw err;
|
||||
|
// }
|
||||
|
// },
|
||||
|
|
||||
|
// // 获取验证码倒计时
|
||||
|
// getCodeInterval() {
|
||||
|
// this.showInterval = true;
|
||||
|
// this.codeTimer = setInterval(() => {
|
||||
|
// if (this.interval === 0) {
|
||||
|
// clearInterval(this.codeTimer);
|
||||
|
// this.codeTimer = null;
|
||||
|
// this.showInterval = false;
|
||||
|
// this.interval = 120;
|
||||
|
// return;
|
||||
|
// }
|
||||
|
// this.interval = this.interval - 1;
|
||||
|
// }, 1000);
|
||||
|
// },
|
||||
|
|
||||
|
// // 验证信息
|
||||
|
// checkRules() {
|
||||
|
// // const { smsCode, phone, user } = this;
|
||||
|
// if (!this.verifyPhone(phone.value)) {
|
||||
|
// uni.$ui.showToast('请输入正确的手机号');
|
||||
|
// return false;
|
||||
|
// }
|
||||
|
// if (!smsCode.value) {
|
||||
|
// uni.$ui.showToast('验证码无效');
|
||||
|
// return false;
|
||||
|
// }
|
||||
|
|
||||
|
// if (phone.value === user.value.phone) {
|
||||
|
// uni.$ui.showToast('新手机号不能与旧手机号相同');
|
||||
|
// return;
|
||||
|
// }
|
||||
|
// return true;
|
||||
|
// },
|
||||
|
|
||||
|
// // 粘贴
|
||||
|
// setCode() {
|
||||
|
// // 获取粘贴板内容
|
||||
|
// // 小程序平台
|
||||
|
// //#ifdef MP-WEIXIN
|
||||
|
// var _this = this
|
||||
|
// uni.getClipboardData({
|
||||
|
// success (res) {
|
||||
|
// _this.smsCode = res.data;
|
||||
|
// }
|
||||
|
// });
|
||||
|
// //#endif
|
||||
|
|
||||
|
// // 非小程序平台
|
||||
|
// //#ifndef MP-WEIXIN
|
||||
|
// this.getClipboardContents()
|
||||
|
// //#endif
|
||||
|
// },
|
||||
|
|
||||
|
// // 非小程序平台粘贴
|
||||
|
// async getClipboardContents() {
|
||||
|
// try {
|
||||
|
// const text = await navigator.clipboard.readText();
|
||||
|
// this.smsCode = text;
|
||||
|
// } catch (err) {
|
||||
|
// console.error('Failed to read clipboard contents: ', err);
|
||||
|
// }
|
||||
|
// },
|
||||
|
|
||||
|
// /**
|
||||
|
// * 验证手机号格式
|
||||
|
// * @param {string} phone 手机号
|
||||
|
// */
|
||||
|
// verifyPhone(phone) {
|
||||
|
// const phoneExg = /^1\d{10}$/;
|
||||
|
// return phoneExg.test(phone);
|
||||
|
// },
|
||||
|
|
||||
|
// /**
|
||||
|
// * 验证账号/密码 格式
|
||||
|
// * @param {string} account 账号
|
||||
|
// */
|
||||
|
// verifyLoginname(account) {
|
||||
|
// const accountExg = /^[a-zA-Z0-9._-]{2,20}$/;
|
||||
|
// return accountExg.test(account);
|
||||
|
// },
|
||||
|
|
||||
|
// // 微信登录
|
||||
|
// handleWxLogin() {
|
||||
|
// const origin = 'https://test.tall.wiki/pt-mui'; // 测试
|
||||
|
// const appid = 'wxd1842e073e0e6d91';
|
||||
|
// const state = 'wx_web';
|
||||
|
// const href = 'https://open.weixin.qq.com/connect/qrconnect';
|
||||
|
// // eslint-disable-next-line
|
||||
|
// window.location.href =
|
||||
|
// `${href}?appid=${appid}&redirect_uri=${origin}&response_type=code&scope=snsapi_login&state=${state}#wechat_redirect`;
|
||||
|
// },
|
||||
|
// // }
|
||||
|
// };
|
@ -0,0 +1,123 @@ |
|||||
|
import { ref, computed } from 'vue'; |
||||
|
import { useStore } from 'vuex'; |
||||
|
import clipboard from "@/common/js/dc-clipboard/clipboard.js" |
||||
|
|
||||
|
export default function userMixin() { |
||||
|
const store = useStore(); |
||||
|
const user = computed(() => store.state.user.user); |
||||
|
const rules = ref({ |
||||
|
phone: [{ |
||||
|
required: true, |
||||
|
message: '请输入手机号', |
||||
|
trigger: ['change', 'blur'], |
||||
|
}, |
||||
|
{ |
||||
|
validator: (rule, value, callback) => { |
||||
|
// 调用uView自带的js验证规则,详见:https://www.uviewui.com/js/test.html
|
||||
|
return this.$u.test.mobile(value); |
||||
|
}, |
||||
|
message: '手机号码不正确', |
||||
|
// 触发器可以同时用blur和change,二者之间用英文逗号隔开
|
||||
|
trigger: ['change', 'blur'], |
||||
|
} |
||||
|
], |
||||
|
verificationCodeValue: [{ |
||||
|
required: true, |
||||
|
message: '请输入图形验证码', |
||||
|
trigger: ['change', 'blur'], |
||||
|
}, |
||||
|
{ |
||||
|
type: 'number', |
||||
|
message: '图形验证码只能为数字', |
||||
|
trigger: ['change', 'blur'], |
||||
|
} |
||||
|
], |
||||
|
smsCode: [{ |
||||
|
required: true, |
||||
|
message: '请输入验证码', |
||||
|
trigger: ['change', 'blur'], |
||||
|
}, |
||||
|
{ |
||||
|
type: 'number', |
||||
|
message: '验证码只能为数字', |
||||
|
trigger: ['change', 'blur'], |
||||
|
} |
||||
|
], |
||||
|
account: [{ |
||||
|
required: true, |
||||
|
message: '请输入用户名', |
||||
|
trigger: ['change', 'blur'], |
||||
|
}, |
||||
|
{ |
||||
|
min: 2, |
||||
|
max: 20, |
||||
|
message: '用户名长度在2到20个字符', |
||||
|
trigger: ['change', 'blur'], |
||||
|
}, |
||||
|
{ |
||||
|
pattern: /^[a-zA-Z0-9._-]{2,20}$/, |
||||
|
message: '请输入2-20位字母、数字、汉字或字符"_ - ."', |
||||
|
trigger: ['change', 'blur'], |
||||
|
} |
||||
|
], |
||||
|
password: [{ |
||||
|
required: true, |
||||
|
message: '请输入密码', |
||||
|
trigger: ['change', 'blur'], |
||||
|
}, |
||||
|
{ |
||||
|
min: 6, |
||||
|
max: 20, |
||||
|
message: '密码长度在6到20个字符', |
||||
|
trigger: ['change', 'blur'], |
||||
|
}, |
||||
|
{ |
||||
|
// 正则不能含有两边的引号
|
||||
|
pattern: /^[a-zA-Z0-9._-]{6,20}$/, |
||||
|
message: '请输入6-20位字母、数字、汉字或字符"_ - ."', |
||||
|
trigger: ['change', 'blur'], |
||||
|
} |
||||
|
], |
||||
|
}); |
||||
|
const errorType = ['message']; |
||||
|
const labelPosition = 'left'; |
||||
|
const border = false; |
||||
|
const smsCode = ref(''); // 短信验证码
|
||||
|
const showInterval = ref(false); |
||||
|
const interval = ref(120); |
||||
|
const codeTimer = ref(null); |
||||
|
const showPaste = ref(false); |
||||
|
|
||||
|
// 获取图形验证码
|
||||
|
async function getImageCode() { |
||||
|
console.log('5555') |
||||
|
uni.$ui.showLoading(); |
||||
|
try { |
||||
|
const data = await uni.$u.api.getImageCode(); |
||||
|
const { imageBase64, verificationCodeId } = data; |
||||
|
imageBase64 = imageBase64 || ''; |
||||
|
verificationCodeId = verificationCodeId || ''; |
||||
|
uni.$ui.hideLoading(); |
||||
|
} catch (error) { |
||||
|
uni.$ui.hideLoading(); |
||||
|
uni.$ui.showToast(error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
rules, |
||||
|
errorType, |
||||
|
labelPosition, |
||||
|
border, |
||||
|
getImageCode, |
||||
|
// hasvalue,
|
||||
|
// getCode,
|
||||
|
// getCodeInterval,
|
||||
|
// checkRules,
|
||||
|
// setCode,
|
||||
|
// getClipboardContents,
|
||||
|
// verifyPhone,
|
||||
|
// verifyLoginname,
|
||||
|
// handleWxLogin
|
||||
|
} |
||||
|
} |
@ -1,135 +1,135 @@ |
|||||
<template> |
<template> |
||||
<!-- <view class="flex flex-col h-full bg-gray-50" @click="openAuth"> --> |
<!-- <view class="flex flex-col h-full bg-gray-50" @click="openAuth"> --> |
||||
<view class="flex flex-col h-full bg-gray-50"> |
<view class="flex flex-col h-full bg-gray-50"> |
||||
<view class="relative" @touchmove="onMove"> |
<view class="relative" @touchmove="onMove"> |
||||
<!-- 日历 --> |
<!-- 日历 --> |
||||
<Calendar @selected-change="onDateChange" :show-back="true" ref="calendar" @handleFindPoint="handleFindPoint" /> |
<Calendar @selected-change="onDateChange" :show-back="true" ref="calendar" @handleFindPoint="handleFindPoint" /> |
||||
<!-- 上传 导入wbs --> |
<!-- 上传 导入wbs --> |
||||
<Upload @success="onUploadSuccess" @error="onUploadError" /> |
<Upload @success="onUploadSuccess" @error="onUploadError" /> |
||||
</view> |
</view> |
||||
|
|
||||
<!-- 项目列表 --> |
<!-- 项目列表 --> |
||||
<Projects @getProjects="getProjects" class="flex-1 overflow-y-auto" /> |
<Projects @getProjects="getProjects" class="flex-1 overflow-y-auto" /> |
||||
|
|
||||
<!-- 全局提示框 --> |
<!-- 全局提示框 --> |
||||
<u-top-tips ref="uTips"></u-top-tips> |
<u-top-tips ref="uTips"></u-top-tips> |
||||
</view> |
</view> |
||||
</template> |
</template> |
||||
|
|
||||
<script setup> |
<script setup> |
||||
import { reactive, computed, watchEffect, ref } from 'vue'; |
import { reactive, computed, watchEffect, ref } from 'vue'; |
||||
import { useStore } from 'vuex'; |
import { useStore } from 'vuex'; |
||||
import dayjs from 'dayjs'; |
import dayjs from 'dayjs'; |
||||
|
|
||||
const store = useStore(); |
const store = useStore(); |
||||
const token = computed(() => store.state.user.token); |
const token = computed(() => store.state.user.token); |
||||
const uTips = ref(null); |
const uTips = ref(null); |
||||
|
|
||||
const data = reactive({ |
const data = reactive({ |
||||
calendar: null, |
calendar: null, |
||||
days: [], |
days: [], |
||||
}); |
}); |
||||
|
|
||||
// 监听token |
// 监听token |
||||
watchEffect(() => { |
watchEffect(() => { |
||||
if (!token.value) return; |
if (!token.value) return; |
||||
if (token.value) { |
if (token.value) { |
||||
getProjects(); |
getProjects(); |
||||
handleFindPoint(); |
handleFindPoint(); |
||||
} |
} |
||||
}); |
}); |
||||
|
|
||||
// 获取项目列表 |
// 获取项目列表 |
||||
function getProjects(start = dayjs().startOf('day').valueOf(), end = dayjs().endOf('day').valueOf()) { |
function getProjects(start = dayjs().startOf('day').valueOf(), end = dayjs().endOf('day').valueOf()) { |
||||
// const data = await this.$u.api.getProjects(start, end); |
// const data = await this.$u.api.getProjects(start, end); |
||||
uni.$catchReq.getProjects(start, end, (err, data) => { |
uni.$catchReq.getProjects(start, end, (err, data) => { |
||||
if (err) { |
if (err) { |
||||
console.error('err: ', err); |
console.error('err: ', err); |
||||
} else { |
} else { |
||||
data.forEach(item => { |
data.forEach(item => { |
||||
item.show = false; |
item.show = false; |
||||
}); |
}); |
||||
store.commit('project/setProjects', data); |
store.commit('project/setProjects', data); |
||||
} |
} |
||||
}); |
}); |
||||
} |
} |
||||
|
|
||||
async function handleFindPoint(start, end) { |
async function handleFindPoint(start, end) { |
||||
try { |
try { |
||||
const startTime = start || dayjs().startOf('month').valueOf(); |
const startTime = start || dayjs().startOf('month').valueOf(); |
||||
const endTime = end || dayjs().endOf('month').valueOf(); |
const endTime = end || dayjs().endOf('month').valueOf(); |
||||
const res = await uni.$u.api.findRedPoint(startTime, endTime); |
const res = await uni.$u.api.findRedPoint(startTime, endTime); |
||||
store.commit('project/setDotList', res); |
store.commit('project/setDotList', res); |
||||
} catch (error) { |
} catch (error) { |
||||
console.log('error: ', error); |
console.log('error: ', error); |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
// 点击了某个日期 |
// 点击了某个日期 |
||||
const onDateChange = event => { |
const onDateChange = event => { |
||||
const day = dayjs(event.fullDate); |
const day = dayjs(event.fullDate); |
||||
const start = day.startOf('date').valueOf(); |
const start = day.startOf('date').valueOf(); |
||||
const end = day.endOf('date').valueOf(); |
const end = day.endOf('date').valueOf(); |
||||
getProjects(start, end); |
getProjects(start, end); |
||||
}; |
}; |
||||
|
|
||||
// 导入成功 |
// 导入成功 |
||||
const onUploadSuccess = () => { |
const onUploadSuccess = () => { |
||||
uTips.show({ |
uTips.show({ |
||||
title: '导入成功,即将打开新项目', |
title: '导入成功,即将打开新项目', |
||||
type: 'success', |
type: 'success', |
||||
duration: '3000', |
duration: '3000', |
||||
}); |
}); |
||||
}; |
}; |
||||
|
|
||||
// 导入失败 |
// 导入失败 |
||||
const onUploadError = error => { |
const onUploadError = error => { |
||||
uTips.show({ |
uTips.show({ |
||||
title: error || '导入失败', |
title: error || '导入失败', |
||||
type: 'error', |
type: 'error', |
||||
duration: '6000', |
duration: '6000', |
||||
}); |
}); |
||||
}; |
}; |
||||
|
|
||||
// 监听触摸滑动 切换日历的模式 月/周 |
// 监听触摸滑动 切换日历的模式 月/周 |
||||
function onMove(event) { |
function onMove(event) { |
||||
const y = event.changedTouches[0].pageY; |
const y = event.changedTouches[0].pageY; |
||||
if (y - prevY > 0) { |
if (y - prevY > 0) { |
||||
// 向下滑动 如果是周视图weekMode=true 就 变成 月视图weekMode=false |
// 向下滑动 如果是周视图weekMode=true 就 变成 月视图weekMode=false |
||||
data.value.calendar.weekMode && (data.value.calendar.weekMode = false); |
data.value.calendar.weekMode && (data.value.calendar.weekMode = false); |
||||
} else if (y - prevY < 0) { |
} else if (y - prevY < 0) { |
||||
// 向上滑动 如果是月视图weekMode=false 就变成 周视图weekMode=true |
// 向上滑动 如果是月视图weekMode=false 就变成 周视图weekMode=true |
||||
!data.value.calendar.weekMode && (data.value.calendar.weekMode = true); |
!data.value.calendar.weekMode && (data.value.calendar.weekMode = true); |
||||
} |
} |
||||
prevY = y; |
prevY = y; |
||||
data.value.calendar.initDate(); |
data.value.calendar.initDate(); |
||||
} |
} |
||||
</script> |
</script> |
||||
|
|
||||
<style> |
<style> |
||||
.content { |
.content { |
||||
display: flex; |
display: flex; |
||||
flex-direction: column; |
flex-direction: column; |
||||
align-items: center; |
align-items: center; |
||||
justify-content: center; |
justify-content: center; |
||||
} |
} |
||||
|
|
||||
.logo { |
.logo { |
||||
height: 200rpx; |
height: 200rpx; |
||||
width: 200rpx; |
width: 200rpx; |
||||
margin-top: 200rpx; |
margin-top: 200rpx; |
||||
margin-left: auto; |
margin-left: auto; |
||||
margin-right: auto; |
margin-right: auto; |
||||
margin-bottom: 50rpx; |
margin-bottom: 50rpx; |
||||
} |
} |
||||
|
|
||||
.text-area { |
.text-area { |
||||
display: flex; |
display: flex; |
||||
justify-content: center; |
justify-content: center; |
||||
} |
} |
||||
|
|
||||
.title { |
.title { |
||||
font-size: 36rpx; |
font-size: 36rpx; |
||||
color: #8f8f94; |
color: #8f8f94; |
||||
} |
} |
||||
</style> |
</style> |
||||
|
@ -0,0 +1,94 @@ |
|||||
|
<template> |
||||
|
<view class="u-p-l-50 u-p-r-50 u-p-t-30"> |
||||
|
<u-form :model="model" ref="uForm" :rules="mixinInit.rules" :error-type="mixinInit.errorType"> |
||||
|
<u-form-item :label-position="mixinInit.labelPosition" label="用户名" prop="account" label-width="150"> |
||||
|
<u-input :border="mixinInit.border" placeholder="请输入用户名" v-model="model.account" type="text"></u-input> |
||||
|
</u-form-item> |
||||
|
<u-form-item :label-position="mixinInit.labelPosition" label="密码" prop="password" label-width="150"> |
||||
|
<u-input :password-icon="true" :border="mixinInit.border" type="password" v-model="model.password" placeholder="请输入密码"> |
||||
|
</u-input> |
||||
|
</u-form-item> |
||||
|
<view class="flex flex-nowrap"> |
||||
|
<view class="flex-sub"></view> |
||||
|
<view class="u-m-t-30 u-font-12 text-gray-400" @click="openPage('/pages/user/forgetPassword')">忘记密码</view> |
||||
|
</view> |
||||
|
</u-form> |
||||
|
|
||||
|
<view class="u-m-t-50"> |
||||
|
<u-button @click="submit" type="primary">立即登录</u-button> |
||||
|
</view> |
||||
|
|
||||
|
<view class="flex justify-between"> |
||||
|
<view class="u-m-t-30" style="color: #2885ED;" @click="openPage('/pages/user/rigister')"> 新用户注册</view> |
||||
|
<view class="u-m-t-30" style="color: #2885ED;" @click="openPage('/pages/user/login')">手机号登录 </view> |
||||
|
</view> |
||||
|
|
||||
|
<view style="margin-top: 200rpx;text-align: center; color: #999999;font-size: 35rpx;"> |
||||
|
快速登录 |
||||
|
</view> |
||||
|
<view style="text-align: center; margin-top: 20rpx;"> |
||||
|
<image src="/common/img/weixinIcon.png" mode="" style="width: 85rpx;height: 85rpx;"></image> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref, computed } from 'vue'; |
||||
|
import { useStore } from 'vuex'; |
||||
|
import userMixin from '@/hooks/user/userMixin' |
||||
|
|
||||
|
const store = useStore(); |
||||
|
const mixinInit = userMixin(); |
||||
|
const userInfo = uni.$storage.getStorageSync('user'); |
||||
|
const user = ref({}); |
||||
|
// const uForm = ref(null); |
||||
|
const model = ref({ |
||||
|
account: '', |
||||
|
password: '' |
||||
|
}) |
||||
|
|
||||
|
|
||||
|
if (userInfo) { |
||||
|
user.value = JSON.parse(userInfo); |
||||
|
} |
||||
|
|
||||
|
const submit = () => { |
||||
|
// uForm.value.validate().then().catch(); |
||||
|
} |
||||
|
|
||||
|
async function login() { |
||||
|
try { |
||||
|
uni.$ui.showLoading(); |
||||
|
if (account.value === user.value.account) { |
||||
|
uni.$ui.showToast('当前账户已登录'); |
||||
|
} else { |
||||
|
const params = ref({ |
||||
|
client: 1, |
||||
|
data: { |
||||
|
identifier: account.value, |
||||
|
credential: password.value, |
||||
|
}, |
||||
|
type: 3, |
||||
|
}); |
||||
|
|
||||
|
let res = await uni.$u.api.signin(params.value); |
||||
|
store.commit('user/setToken', res.token); |
||||
|
store.commit('user/setUser', res); |
||||
|
uni.$storage.setStorageSync('anyringToken', res.token || ''); |
||||
|
uni.$storage.setStorageSync('user', JSON.stringify(res)); |
||||
|
} |
||||
|
|
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/index/index' |
||||
|
}); |
||||
|
|
||||
|
uni.$ui.hideLoading(); |
||||
|
} catch (error) { |
||||
|
uni.$ui.hideLoading(); |
||||
|
uni.$ui.showToast(error); |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
</style> |
@ -0,0 +1,266 @@ |
|||||
|
import { ref, computed } from 'vue'; |
||||
|
import { useStore } from 'vuex'; |
||||
|
import clipboard from "@/common/js/dc-clipboard/clipboard.js" |
||||
|
|
||||
|
export default function mixinInit { |
||||
|
const store = useStore(); |
||||
|
const user = computed(() => store.state.user.user); |
||||
|
const rules = ref({ |
||||
|
phone: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
message: '请输入手机号', |
||||
|
trigger: ['change','blur'], |
||||
|
}, |
||||
|
{ |
||||
|
validator: (rule, value, callback) => { |
||||
|
// 调用uView自带的js验证规则,详见:https://www.uviewui.com/js/test.html
|
||||
|
return this.$u.test.mobile(value); |
||||
|
}, |
||||
|
message: '手机号码不正确', |
||||
|
// 触发器可以同时用blur和change,二者之间用英文逗号隔开
|
||||
|
trigger: ['change','blur'], |
||||
|
} |
||||
|
], |
||||
|
verificationCodeValue: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
message: '请输入图形验证码', |
||||
|
trigger: ['change','blur'], |
||||
|
}, |
||||
|
{ |
||||
|
type: 'number', |
||||
|
message: '图形验证码只能为数字', |
||||
|
trigger: ['change','blur'], |
||||
|
} |
||||
|
], |
||||
|
smsCode: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
message: '请输入验证码', |
||||
|
trigger: ['change','blur'], |
||||
|
}, |
||||
|
{ |
||||
|
type: 'number', |
||||
|
message: '验证码只能为数字', |
||||
|
trigger: ['change','blur'], |
||||
|
} |
||||
|
], |
||||
|
account: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
message: '请输入用户名', |
||||
|
trigger: ['change','blur'], |
||||
|
}, |
||||
|
{ |
||||
|
min: 2, |
||||
|
max: 20, |
||||
|
message: '用户名长度在2到20个字符', |
||||
|
trigger: ['change','blur'], |
||||
|
}, |
||||
|
{ |
||||
|
pattern: /^[a-zA-Z0-9._-]{2,20}$/, |
||||
|
message: '请输入2-20位字母、数字、汉字或字符"_ - ."', |
||||
|
trigger: ['change','blur'], |
||||
|
} |
||||
|
], |
||||
|
password: [ |
||||
|
{ |
||||
|
required: true, |
||||
|
message: '请输入密码', |
||||
|
trigger: ['change','blur'], |
||||
|
}, |
||||
|
{ |
||||
|
min: 6, |
||||
|
max: 20, |
||||
|
message: '密码长度在6到20个字符', |
||||
|
trigger: ['change','blur'], |
||||
|
}, |
||||
|
{ |
||||
|
// 正则不能含有两边的引号
|
||||
|
pattern: /^[a-zA-Z0-9._-]{6,20}$/, |
||||
|
message: '请输入6-20位字母、数字、汉字或字符"_ - ."', |
||||
|
trigger: ['change','blur'], |
||||
|
} |
||||
|
], |
||||
|
}); |
||||
|
const errorType = ref(['message']); |
||||
|
const labelPosition = ref('left'); |
||||
|
const border = ref(false); |
||||
|
const smsCode = ref(''); // 短信验证码
|
||||
|
const showInterval = ref(false); |
||||
|
const interval = ref(120); |
||||
|
const codeTimer = ref(null); |
||||
|
const showPaste = ref(false); |
||||
|
|
||||
|
return { |
||||
|
errorType, |
||||
|
// getImageCode,
|
||||
|
// hasvalue,
|
||||
|
// getCode,
|
||||
|
// getCodeInterval,
|
||||
|
// checkRules,
|
||||
|
// setCode,
|
||||
|
// getClipboardContents,
|
||||
|
// verifyPhone,
|
||||
|
// verifyLoginname,
|
||||
|
// handleWxLogin
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
// const mixin = {
|
||||
|
// computed: mapState('user', ['user']),
|
||||
|
|
||||
|
// onReady() {
|
||||
|
// this.$refs.uForm.setRules(this.rules);
|
||||
|
// },
|
||||
|
|
||||
|
// methods: {
|
||||
|
// ...mapActions('user', ['sendCode']),
|
||||
|
|
||||
|
// 获取图形验证码
|
||||
|
// async getImageCode() {
|
||||
|
// this.$util.showLoading();
|
||||
|
// try {
|
||||
|
// const data = await uni.$u.api.getImageCode();
|
||||
|
// const { imageBase64, verificationCodeId } = data;
|
||||
|
// this.imageBase64 = imageBase64 || '';
|
||||
|
// this.verificationCodeId = verificationCodeId || '';
|
||||
|
// uni.hideLoading();
|
||||
|
// } catch (error) {
|
||||
|
// uni.hideLoading();
|
||||
|
// uni.$ui.showToast(error);
|
||||
|
// }
|
||||
|
// },
|
||||
|
|
||||
|
// //有图片验证码的值
|
||||
|
// hasvalue() {
|
||||
|
// if(this.model.smsCode || this.model.showPaste) return
|
||||
|
// if (!this.verifyPhone(this.model.phone)) {
|
||||
|
// uni.$ui.showToast('请输入正确的手机号');
|
||||
|
// return;
|
||||
|
// }
|
||||
|
// if (!this.model.verificationCodeValue) {
|
||||
|
// uni.$ui.showToast('请输入图形验证码');
|
||||
|
// return;
|
||||
|
// }
|
||||
|
// this.getCode();
|
||||
|
// },
|
||||
|
|
||||
|
// // 获取验证码
|
||||
|
// async getCode() {
|
||||
|
// try {
|
||||
|
// const { phone, verificationCodeValue } = this.model;
|
||||
|
// const { verificationCodeId } = this;
|
||||
|
|
||||
|
// if (!verificationCodeId || !verificationCodeValue) {
|
||||
|
// uni.$ui.showToast('缺少图形验证码参数');
|
||||
|
// return;
|
||||
|
// }
|
||||
|
// const params = {
|
||||
|
// phone,
|
||||
|
// verificationCodeId,
|
||||
|
// verificationCodeValue,
|
||||
|
// };
|
||||
|
// const date = await store.dispatch('user/sendCode', params);
|
||||
|
// getCodeInterval();
|
||||
|
// showPaste.value = true;
|
||||
|
// } catch (err) {
|
||||
|
// throw err;
|
||||
|
// }
|
||||
|
// },
|
||||
|
|
||||
|
// // 获取验证码倒计时
|
||||
|
// getCodeInterval() {
|
||||
|
// this.showInterval = true;
|
||||
|
// this.codeTimer = setInterval(() => {
|
||||
|
// if (this.interval === 0) {
|
||||
|
// clearInterval(this.codeTimer);
|
||||
|
// this.codeTimer = null;
|
||||
|
// this.showInterval = false;
|
||||
|
// this.interval = 120;
|
||||
|
// return;
|
||||
|
// }
|
||||
|
// this.interval = this.interval - 1;
|
||||
|
// }, 1000);
|
||||
|
// },
|
||||
|
|
||||
|
// // 验证信息
|
||||
|
// checkRules() {
|
||||
|
// // const { smsCode, phone, user } = this;
|
||||
|
// if (!this.verifyPhone(phone.value)) {
|
||||
|
// uni.$ui.showToast('请输入正确的手机号');
|
||||
|
// return false;
|
||||
|
// }
|
||||
|
// if (!smsCode.value) {
|
||||
|
// uni.$ui.showToast('验证码无效');
|
||||
|
// return false;
|
||||
|
// }
|
||||
|
|
||||
|
// if (phone.value === user.value.phone) {
|
||||
|
// uni.$ui.showToast('新手机号不能与旧手机号相同');
|
||||
|
// return;
|
||||
|
// }
|
||||
|
// return true;
|
||||
|
// },
|
||||
|
|
||||
|
// // 粘贴
|
||||
|
// setCode() {
|
||||
|
// // 获取粘贴板内容
|
||||
|
// // 小程序平台
|
||||
|
// //#ifdef MP-WEIXIN
|
||||
|
// var _this = this
|
||||
|
// uni.getClipboardData({
|
||||
|
// success (res) {
|
||||
|
// _this.smsCode = res.data;
|
||||
|
// }
|
||||
|
// });
|
||||
|
// //#endif
|
||||
|
|
||||
|
// // 非小程序平台
|
||||
|
// //#ifndef MP-WEIXIN
|
||||
|
// this.getClipboardContents()
|
||||
|
// //#endif
|
||||
|
// },
|
||||
|
|
||||
|
// // 非小程序平台粘贴
|
||||
|
// async getClipboardContents() {
|
||||
|
// try {
|
||||
|
// const text = await navigator.clipboard.readText();
|
||||
|
// this.smsCode = text;
|
||||
|
// } catch (err) {
|
||||
|
// console.error('Failed to read clipboard contents: ', err);
|
||||
|
// }
|
||||
|
// },
|
||||
|
|
||||
|
// /**
|
||||
|
// * 验证手机号格式
|
||||
|
// * @param {string} phone 手机号
|
||||
|
// */
|
||||
|
// verifyPhone(phone) {
|
||||
|
// const phoneExg = /^1\d{10}$/;
|
||||
|
// return phoneExg.test(phone);
|
||||
|
// },
|
||||
|
|
||||
|
// /**
|
||||
|
// * 验证账号/密码 格式
|
||||
|
// * @param {string} account 账号
|
||||
|
// */
|
||||
|
// verifyLoginname(account) {
|
||||
|
// const accountExg = /^[a-zA-Z0-9._-]{2,20}$/;
|
||||
|
// return accountExg.test(account);
|
||||
|
// },
|
||||
|
|
||||
|
// // 微信登录
|
||||
|
// handleWxLogin() {
|
||||
|
// const origin = 'https://test.tall.wiki/pt-mui'; // 测试
|
||||
|
// const appid = 'wxd1842e073e0e6d91';
|
||||
|
// const state = 'wx_web';
|
||||
|
// const href = 'https://open.weixin.qq.com/connect/qrconnect';
|
||||
|
// // eslint-disable-next-line
|
||||
|
// window.location.href =
|
||||
|
// `${href}?appid=${appid}&redirect_uri=${origin}&response_type=code&scope=snsapi_login&state=${state}#wechat_redirect`;
|
||||
|
// },
|
||||
|
// // }
|
||||
|
// };
|
@ -0,0 +1,9 @@ |
|||||
|
<template> |
||||
|
<view class="deliver-container">p-deliver</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
|
||||
|
</script> |
||||
|
|
||||
|
<style lang="scss"></style> |
@ -0,0 +1,10 @@ |
|||||
|
<template> |
||||
|
<!-- 任务名插件 --> |
||||
|
<theme> |
||||
|
<view>{{ task.name }}</view> |
||||
|
</theme> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
defineProps({ task: { type: Object, default: () => {} } }); |
||||
|
</script> |
@ -1,48 +1,58 @@ |
|||||
import { createStore } from 'vuex'; |
import { createStore } from 'vuex'; |
||||
import user from './user/index.js'; |
|
||||
import socket from './socket/index.js'; |
|
||||
import project from './project/index.js'; |
import project from './project/index.js'; |
||||
import role from './role/index.js'; |
import role from './role/index.js'; |
||||
|
import socket from './socket/index.js'; |
||||
import task from './task/index.js'; |
import task from './task/index.js'; |
||||
|
import user from './user/index.js'; |
||||
|
|
||||
// 不属于具体模块的 应用级的 store内容
|
// 不属于具体模块的 应用级的 store内容
|
||||
const state = { |
const state = { |
||||
networkConnected: true, // 网络是否连接
|
theme: 'theme-default', |
||||
forceUseStorage: true, // 强制启用storage
|
networkConnected: true, // 网络是否连接
|
||||
systemInfo: null, // 系统设备信息
|
forceUseStorage: true, // 强制启用storage
|
||||
|
systemInfo: null, // 系统设备信息
|
||||
}; |
}; |
||||
|
|
||||
const getters = { |
const getters = { |
||||
// 是否启用本地存储
|
// 是否启用本地存储
|
||||
// 设置了强制启用本地存储 或者 没有网络连接的时候
|
// 设置了强制启用本地存储 或者 没有网络连接的时候
|
||||
useStorage({ networkConnected, forceUseStorage }) { |
useStorage({ networkConnected, forceUseStorage }) { |
||||
return forceUseStorage || !networkConnected; |
return forceUseStorage || !networkConnected; |
||||
}, |
}, |
||||
}; |
}; |
||||
|
|
||||
const mutations = { |
const mutations = { |
||||
/** |
/** |
||||
* 设置网络是否连接的变量 |
* 设置网络是否连接的变量 |
||||
* @param {*} state |
* @param {*} state |
||||
* @param {boolean} networkConnected |
* @param {boolean} networkConnected |
||||
*/ |
*/ |
||||
setNetworkConnected(state, networkConnected) { |
setNetworkConnected(state, networkConnected) { |
||||
state.networkConnected = networkConnected; |
state.networkConnected = networkConnected; |
||||
}, |
}, |
||||
|
|
||||
|
/** |
||||
|
* 设置系统信息的数据 |
||||
|
* @param {object} state |
||||
|
* @param {object | null} data 获取到的数据 |
||||
|
*/ |
||||
|
setSystemInfo(state, data) { |
||||
|
state.systemInfo = data; |
||||
|
}, |
||||
|
|
||||
/** |
/** |
||||
* 设置系统信息的数据 |
* 设置主题 |
||||
* @param {object} state |
* @param {object} state |
||||
* @param {object | null} data 获取到的数据 |
* @param {string} theme 主题名称 默认theme-default |
||||
*/ |
*/ |
||||
setSystemInfo(state, data) { |
setTheme(state, theme) { |
||||
state.systemInfo = data; |
state.theme = theme || 'theme-default'; |
||||
}, |
}, |
||||
}; |
}; |
||||
|
|
||||
export default createStore({ |
export default createStore({ |
||||
state, |
state, |
||||
getters, |
getters, |
||||
mutations, |
mutations, |
||||
modules: {user, socket, project, role, task} |
modules: { user, socket, project, role, task }, |
||||
}); |
}); |
||||
|
Loading…
Reference in new issue