提交一波轮子
This commit is contained in:
@@ -6,7 +6,7 @@ const start = () => {
|
|||||||
easycom: {
|
easycom: {
|
||||||
autoscan: true,
|
autoscan: true,
|
||||||
custom: {
|
custom: {
|
||||||
"^(K|V)(.*)": "@/components/$1$2.vue",
|
"^(Ai|V)(.*)": "@/components/$1$2.vue",
|
||||||
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
|
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -22,6 +22,10 @@
|
|||||||
"@dcloudio/uni-mp-weixin": "3.0.0-3061420221215001",
|
"@dcloudio/uni-mp-weixin": "3.0.0-3061420221215001",
|
||||||
"@dcloudio/uni-quickapp-webview": "3.0.0-3061420221215001",
|
"@dcloudio/uni-quickapp-webview": "3.0.0-3061420221215001",
|
||||||
"@dcloudio/uni-ui": "^1.4.23",
|
"@dcloudio/uni-ui": "^1.4.23",
|
||||||
|
"axios": "^1.2.2",
|
||||||
|
"axios-miniprogram-adapter": "^0.3.5",
|
||||||
|
"dayjs": "^1.11.7",
|
||||||
|
"query-string": "^8.1.0",
|
||||||
"vue": "^3.2.45",
|
"vue": "^3.2.45",
|
||||||
"vue-i18n": "^9.1.9"
|
"vue-i18n": "^9.1.9"
|
||||||
},
|
},
|
||||||
|
|||||||
61
wxmp/src/components/AiGroup.vue
Normal file
61
wxmp/src/components/AiGroup.vue
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<template>
|
||||||
|
<section class="AiGroup" :class="{noBorder,description}" :style="{paddingLeft:left+'rpx'}">
|
||||||
|
<div class="groupHeader" v-if="title" v-text="title"/>
|
||||||
|
<slot/>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "AiGroup",
|
||||||
|
provide() {
|
||||||
|
return {
|
||||||
|
labelColor: this.labelColor,
|
||||||
|
description: this.description,
|
||||||
|
activeStep: this.activeStep
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
title: String,
|
||||||
|
noBorder: Boolean,
|
||||||
|
left: {default: 32},
|
||||||
|
labelColor: {default: "#333"},
|
||||||
|
description: {default: false}, //用于展示则不会又红星,会把标签的内间距去掉
|
||||||
|
activeStep: {default: 1}//用于步骤组件的当前步数
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
items: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.AiGroup {
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: inset 0px -1px 0px 0px #DDDDDD;
|
||||||
|
|
||||||
|
&.noBorder {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
& + .AiGroup {
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.groupHeader {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 36px;
|
||||||
|
padding-left: 20px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.description {
|
||||||
|
.groupHeader {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
124
wxmp/src/components/AiItem.vue
Normal file
124
wxmp/src/components/AiItem.vue
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
<template>
|
||||||
|
<section class="AiItem" :class="{border,readonly}">
|
||||||
|
<div v-if="topLabel" class="topLabel">
|
||||||
|
<div class="labelPane flex">
|
||||||
|
<div class="label" :class="{required,labelBold}" :style="{color}" v-text="label"/>
|
||||||
|
<slot name="sub" v-if="$slots.sub"/>
|
||||||
|
</div>
|
||||||
|
<div class="itemContent">
|
||||||
|
<slot v-if="$slots.default"/>
|
||||||
|
<div v-else v-text="value"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-else class="normal flex">
|
||||||
|
<div class="fill flex">
|
||||||
|
<div class="label" :class="{required,labelBold}" :style="{color}" v-text="label"/>
|
||||||
|
<slot name="sub" v-if="$slots.sub"/>
|
||||||
|
</div>
|
||||||
|
<div class="flexContent">
|
||||||
|
<slot v-if="$slots.default"/>
|
||||||
|
<div v-else v-text="value"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "AiItem",
|
||||||
|
inject: {
|
||||||
|
labelColor: {default: "#333"},
|
||||||
|
description: {default: false}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {default: ""},
|
||||||
|
label: {default: ""},
|
||||||
|
required: Boolean,
|
||||||
|
topLabel: Boolean,
|
||||||
|
border: {default: true},
|
||||||
|
labelBold: Boolean,
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
color: v => v.labelColor,
|
||||||
|
readonly: v => !!v.description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.AiItem {
|
||||||
|
font-family: PingFangSC-Regular, PingFang SC;
|
||||||
|
|
||||||
|
&.border {
|
||||||
|
.normal {
|
||||||
|
border-bottom: 2px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topLabel {
|
||||||
|
border-bottom: 2px solid #ddd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.normal {
|
||||||
|
width: 100%;
|
||||||
|
padding-right: 32px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
height: 112px;
|
||||||
|
|
||||||
|
.flexContent {
|
||||||
|
max-width: 62vw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
padding-left: 20px;
|
||||||
|
font-weight: 400;
|
||||||
|
margin-right: 20px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&.required:before {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
left: 0;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
content: "*";
|
||||||
|
color: #f46;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.labelBold {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 34px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep.topLabel {
|
||||||
|
padding: 32px 32px 32px 0;
|
||||||
|
|
||||||
|
.labelPane {
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.itemContent {
|
||||||
|
padding-left: 20px;
|
||||||
|
|
||||||
|
.AiMore > .u-icon {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//展示模式下的特有样式
|
||||||
|
&.readonly {
|
||||||
|
.label, .itemContent {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.AiStep:last-of-type {
|
||||||
|
.stepLine {
|
||||||
|
display: none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
74
wxmp/src/components/AiPagePicker.vue
Normal file
74
wxmp/src/components/AiPagePicker.vue
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<template>
|
||||||
|
<section class="AiPagePicker">
|
||||||
|
<div @click="handleJump">
|
||||||
|
<slot v-if="$slots.default"/>
|
||||||
|
<div v-else v-text="selectedLabel"/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import qs from 'query-string'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "AiPagePicker",
|
||||||
|
model: {
|
||||||
|
prop: "value",
|
||||||
|
event: "input"
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {default: ""},
|
||||||
|
type: {default: "sysUser"},
|
||||||
|
nodeKey: {default: "id"},
|
||||||
|
selected: {default: () => []},
|
||||||
|
placeholder: {default: "请选择"},
|
||||||
|
ops: {default: () => ({})},
|
||||||
|
valueObj: Boolean,
|
||||||
|
params: {default: () => ({})},
|
||||||
|
multiple: Boolean
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
configList: {
|
||||||
|
sysUser: {url: "/components/pages/selectSysUser", label: "name"},
|
||||||
|
custom: {...this.ops}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
config() {
|
||||||
|
return this.configList[this.type] || {}
|
||||||
|
},
|
||||||
|
selectedLabel() {
|
||||||
|
let {placeholder, config: {label}} = this
|
||||||
|
return this.selected?.map(e => e[label])?.toString() || placeholder
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleJump() {
|
||||||
|
let {config, nodeKey, valueObj, multiple} = this,
|
||||||
|
selected = (valueObj ? this.value[nodeKey] : this.value) || this.selected?.map(e => e[nodeKey])
|
||||||
|
uni.$once('pagePicker:' + this.type, data => {
|
||||||
|
console.log('发送', data)
|
||||||
|
this.$emit("update:selected", data)
|
||||||
|
this.$emit("select", data)
|
||||||
|
this.$emit("input", valueObj ? data :
|
||||||
|
data ? (multiple ? [data].flat()?.map(e => e[nodeKey]) : data[nodeKey]) : "")
|
||||||
|
})
|
||||||
|
let url = `${config.url}`,
|
||||||
|
qsstr = qs.stringify({
|
||||||
|
selected, nodeKey, multiple, ...this.params
|
||||||
|
})
|
||||||
|
if (!!qsstr) {
|
||||||
|
url += `?${qsstr}`
|
||||||
|
}
|
||||||
|
uni.navigateTo({url})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.AiPagePicker {
|
||||||
|
}
|
||||||
|
</style>
|
||||||
62
wxmp/src/components/pages/submitEvaluation.vue
Normal file
62
wxmp/src/components/pages/submitEvaluation.vue
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<template>
|
||||||
|
<section class="submitEvaluation">
|
||||||
|
<AiGroup>
|
||||||
|
<AiItem label="评价分数" top-label required>
|
||||||
|
<uni-rate v-model="form.score" :size="64" active-color="#F8B425" :min-count="1" inactive-icon="star-fill"/>
|
||||||
|
</AiItem>
|
||||||
|
</AiGroup>
|
||||||
|
<u-gap height="24"/>
|
||||||
|
<AiGroup>
|
||||||
|
<AiItem label="评价详情" top-label required>
|
||||||
|
<uni-easyinput type="textarea" v-model="form.content" placeholder="请简要描述..."/>
|
||||||
|
</AiItem>
|
||||||
|
</AiGroup>
|
||||||
|
<u-gap height="24"/>
|
||||||
|
<AiGroup>
|
||||||
|
<AiItem label="附件" top-label>
|
||||||
|
<uni-file-picker file-mediatype="all" v-model="form.files" :limit="9" mode="grid"/>
|
||||||
|
</AiItem>
|
||||||
|
</AiGroup>
|
||||||
|
<div class="fixed-bottom">
|
||||||
|
<div class="bottomBtn" @click="submit">提交</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "submitEvaluation",
|
||||||
|
appName: "提交评价",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
form: {
|
||||||
|
files: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
submit() {
|
||||||
|
if (!this.form.score) {
|
||||||
|
return this.$toast("请选择评价分数!")
|
||||||
|
}
|
||||||
|
if (!this.form.content) {
|
||||||
|
return this.$toast("请填写评价详情!")
|
||||||
|
}
|
||||||
|
this.$instance.post("/app/appbusinesscompletionevaluation/addOrUpdate", this.form).then(res => {
|
||||||
|
if (res?.code == 0) {
|
||||||
|
this.$toast("提交成功!")
|
||||||
|
setTimeout(() => uni.navigateBack({}), 1500)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad(params) {
|
||||||
|
this.form.bizId = params.bid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.submitEvaluation {
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
import {createSSRApp} from "vue";
|
import {createSSRApp} from "vue";
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
|
import util from "./utils/util";
|
||||||
|
|
||||||
export function createApp() {
|
export function createApp() {
|
||||||
const app = createSSRApp(App);
|
const app = createSSRApp(App);
|
||||||
|
Object.keys(util).map(e => app.config.globalProperties[e] = util[e])
|
||||||
return {
|
return {
|
||||||
app,
|
app,
|
||||||
};
|
};
|
||||||
|
|||||||
19
wxmp/src/utils/coin.js
Normal file
19
wxmp/src/utils/coin.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
export default {
|
||||||
|
cny(money) {
|
||||||
|
if (money) {
|
||||||
|
money.toLocaleString('zh-Hans-CN', {style: 'currency', currency: "CNY"})
|
||||||
|
}
|
||||||
|
return money
|
||||||
|
},
|
||||||
|
cn(money) {
|
||||||
|
let num = parseFloat(money), cnMoney = '',
|
||||||
|
units = '仟佰拾亿仟佰拾万仟佰拾元角分',
|
||||||
|
cnNum = '零壹贰叁肆伍陆柒捌玖'
|
||||||
|
num = num.toFixed(2).replace(/\./g, '')
|
||||||
|
units = units.substring(units.length - num.length)
|
||||||
|
Array.from(num).map((e, i) => {
|
||||||
|
cnMoney += cnNum.charAt(e) + units.charAt(i)
|
||||||
|
})
|
||||||
|
return cnMoney.replace(/零角零分$/, '整').replace(/零[仟佰拾]/g, '零').replace(/零{2,}/g, '零').replace(/零([亿|万])/g, '$1').replace(/零+元/, '元').replace(/亿零{0,3}万/, '亿').replace(/^元/, "零元")
|
||||||
|
}
|
||||||
|
}
|
||||||
56
wxmp/src/utils/dict.js
Normal file
56
wxmp/src/utils/dict.js
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
export default {
|
||||||
|
instance: null,
|
||||||
|
init(instance) {
|
||||||
|
this.instance = instance
|
||||||
|
},
|
||||||
|
dicts() {
|
||||||
|
return uni.getStorageSync('dicts') || [];
|
||||||
|
},
|
||||||
|
load(...code) {
|
||||||
|
return !!this.instance && this.instance.post('/admin/dictionary/queryValsByCodeList?codeList=' + code.join(','), null, {
|
||||||
|
withoutToken: true
|
||||||
|
}).then((res) => {
|
||||||
|
if (res && res.data) {
|
||||||
|
let cacheDicts = {},
|
||||||
|
meta = {};
|
||||||
|
this.dicts().map((e) => (cacheDicts[e.key] = e));
|
||||||
|
res.data.map((e) => (meta[e.key] = e));
|
||||||
|
let dicts = {...cacheDicts, ...meta};
|
||||||
|
uni.setStorageSync('dicts', Object.values(dicts));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getDict(key) {
|
||||||
|
if (this.dicts().length) {
|
||||||
|
let dict = this.dicts().find((e) => e.key == key);
|
||||||
|
return dict ? dict.values : [];
|
||||||
|
} else return [];
|
||||||
|
},
|
||||||
|
getValue(key, label) {
|
||||||
|
if (this.dicts().length) {
|
||||||
|
let dict = this.dicts().find((e) => e.key == key);
|
||||||
|
if (dict) {
|
||||||
|
let item = dict.values.find((v) => v.dictName == label);
|
||||||
|
return item ? item.dictValue : label;
|
||||||
|
} else return label;
|
||||||
|
} else return label;
|
||||||
|
},
|
||||||
|
getLabel(key, value) {
|
||||||
|
if (this.dicts().length) {
|
||||||
|
let dict = this.dicts().find((e) => e.key == key);
|
||||||
|
if (dict) {
|
||||||
|
let item = dict.values.find((v) => v.dictValue == value);
|
||||||
|
return item ? item.dictName : value;
|
||||||
|
} else return value ? value : '';
|
||||||
|
} else return value ? value : '';
|
||||||
|
},
|
||||||
|
getColor(key, value) {
|
||||||
|
if (this.dicts().length) {
|
||||||
|
let dict = this.dicts().find((e) => e.key == key);
|
||||||
|
if (dict) {
|
||||||
|
let item = dict.values.find((v) => v.dictValue == value);
|
||||||
|
return item ? item.dictColor : value;
|
||||||
|
} else return value;
|
||||||
|
} else return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
wxmp/src/utils/http.js
Normal file
29
wxmp/src/utils/http.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import axios from 'axios'
|
||||||
|
import adapter from 'axios-miniprogram-adapter'
|
||||||
|
|
||||||
|
const instance = axios.create({
|
||||||
|
timeout: 600000,
|
||||||
|
withCredentials: true,
|
||||||
|
adapter
|
||||||
|
})
|
||||||
|
const getToken = () => {
|
||||||
|
let vuex = uni.getStorageSync("vuex")
|
||||||
|
return !!vuex ? JSON.parse(vuex).token : null
|
||||||
|
}
|
||||||
|
const source = axios.CancelToken.source();
|
||||||
|
instance.interceptors.request.use(config => {
|
||||||
|
if (config.withoutToken) {
|
||||||
|
return config
|
||||||
|
} else if (getToken()) {
|
||||||
|
config.headers["Authorization"] = getToken()
|
||||||
|
} else {
|
||||||
|
config.cancelToken = source.token
|
||||||
|
source.cancel("用户未验证,取消请求:" + config.url)
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}, err => {
|
||||||
|
console.error(err)
|
||||||
|
return Promise.reject(err)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default instance
|
||||||
238
wxmp/src/utils/identity.js
Normal file
238
wxmp/src/utils/identity.js
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
import dayjs from "./moment";
|
||||||
|
|
||||||
|
|
||||||
|
const PARAMS = {
|
||||||
|
/* 省,直辖市代码表 */
|
||||||
|
provinceAndCitys: {
|
||||||
|
11: '北京',
|
||||||
|
12: '天津',
|
||||||
|
13: '河北',
|
||||||
|
14: '山西',
|
||||||
|
15: '内蒙古',
|
||||||
|
21: '辽宁',
|
||||||
|
22: '吉林',
|
||||||
|
23: '黑龙江',
|
||||||
|
31: '上海',
|
||||||
|
32: '江苏',
|
||||||
|
33: '浙江',
|
||||||
|
34: '安徽',
|
||||||
|
35: '福建',
|
||||||
|
36: '江西',
|
||||||
|
37: '山东',
|
||||||
|
41: '河南',
|
||||||
|
42: '湖北',
|
||||||
|
43: '湖南',
|
||||||
|
44: '广东',
|
||||||
|
45: '广西',
|
||||||
|
46: '海南',
|
||||||
|
50: '重庆',
|
||||||
|
51: '四川',
|
||||||
|
52: '贵州',
|
||||||
|
53: '云南',
|
||||||
|
54: '西藏',
|
||||||
|
61: '陕西',
|
||||||
|
62: '甘肃',
|
||||||
|
63: '青海',
|
||||||
|
64: '宁夏',
|
||||||
|
65: '新疆',
|
||||||
|
71: '台湾',
|
||||||
|
81: '香港',
|
||||||
|
82: '澳门',
|
||||||
|
91: '国外'
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 每位加权因子 */
|
||||||
|
powers: [
|
||||||
|
'7',
|
||||||
|
'9',
|
||||||
|
'10',
|
||||||
|
'5',
|
||||||
|
'8',
|
||||||
|
'4',
|
||||||
|
'2',
|
||||||
|
'1',
|
||||||
|
'6',
|
||||||
|
'3',
|
||||||
|
'7',
|
||||||
|
'9',
|
||||||
|
'10',
|
||||||
|
'5',
|
||||||
|
'8',
|
||||||
|
'4',
|
||||||
|
'2'
|
||||||
|
],
|
||||||
|
|
||||||
|
/* 第18位校检码 */
|
||||||
|
parityBit: ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'],
|
||||||
|
|
||||||
|
/* 性别 */
|
||||||
|
genders: {1: '男', 0: '女'},
|
||||||
|
}
|
||||||
|
|
||||||
|
const Check = {
|
||||||
|
/* 校验地址码 */
|
||||||
|
checkAddressCode(addressCode) {
|
||||||
|
const check = /^[1-9]\d{5}$/.test(addressCode)
|
||||||
|
if (!check) return false
|
||||||
|
return !!PARAMS.provinceAndCitys[parseInt(addressCode.substring(0, 2))]
|
||||||
|
},
|
||||||
|
/* 校验日期码 */
|
||||||
|
checkBirthDayCode(birDayCode) {
|
||||||
|
const check = /^[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))$/.test(
|
||||||
|
birDayCode
|
||||||
|
)
|
||||||
|
if (!check) return false
|
||||||
|
const yyyy = parseInt(birDayCode.substring(0, 4), 10)
|
||||||
|
const mm = parseInt(birDayCode.substring(4, 6), 10)
|
||||||
|
const dd = parseInt(birDayCode.substring(6), 10)
|
||||||
|
const xdata = new Date(yyyy, mm - 1, dd)
|
||||||
|
if (xdata > new Date()) {
|
||||||
|
return false // 生日不能大于当前日期
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
xdata.getFullYear() == yyyy &&
|
||||||
|
xdata.getMonth() == mm - 1 &&
|
||||||
|
xdata.getDate() == dd
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/* 验证校检码 */
|
||||||
|
checkParityBit(idCardNo) {
|
||||||
|
const parityBit = idCardNo.charAt(17).toUpperCase()
|
||||||
|
return this.getParityBit(idCardNo) == parityBit
|
||||||
|
},
|
||||||
|
// 校验15位的身份证号码
|
||||||
|
check15IdCardNo(idCardNo) {
|
||||||
|
// 15位身份证号码的基本校验
|
||||||
|
let check = /^[1-9]\d{7}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}$/.test(
|
||||||
|
idCardNo
|
||||||
|
)
|
||||||
|
if (!check) return false
|
||||||
|
// 校验地址码
|
||||||
|
const addressCode = idCardNo.substring(0, 6)
|
||||||
|
check = this.checkAddressCode(addressCode)
|
||||||
|
if (!check) return false
|
||||||
|
const birDayCode = '19' + idCardNo.substring(6, 12)
|
||||||
|
// 校验日期码
|
||||||
|
return this.checkBirthDayCode(birDayCode)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 校验18位的身份证号码
|
||||||
|
check18IdCardNo(idCardNo) {
|
||||||
|
// 18位身份证号码的基本格式校验
|
||||||
|
let check = /^[1-9]\d{5}[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}(\d|x|X)$/.test(
|
||||||
|
idCardNo
|
||||||
|
)
|
||||||
|
if (!check) return false
|
||||||
|
// 校验地址码
|
||||||
|
const addressCode = idCardNo.substring(0, 6)
|
||||||
|
check = this.checkAddressCode(addressCode)
|
||||||
|
if (!check) return false
|
||||||
|
// 校验日期码
|
||||||
|
const birDayCode = idCardNo.substring(6, 14)
|
||||||
|
check = this.checkBirthDayCode(birDayCode)
|
||||||
|
if (!check) return false
|
||||||
|
// 验证校检码
|
||||||
|
return this.checkParityBit(idCardNo)
|
||||||
|
},
|
||||||
|
/* 计算校检码 */
|
||||||
|
getParityBit(idCardNo) {
|
||||||
|
const id17 = idCardNo.substring(0, 17)
|
||||||
|
/* 加权 */
|
||||||
|
let power = 0
|
||||||
|
for (let i = 0; i < 17; i++) {
|
||||||
|
power += parseInt(id17.charAt(i), 10) * parseInt(PARAMS.powers[i])
|
||||||
|
}
|
||||||
|
/* 取模 */
|
||||||
|
const mod = power % 11
|
||||||
|
return PARAMS.parityBit[mod]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Identity {
|
||||||
|
constructor(code) {
|
||||||
|
this.code = this.getId18(code)
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
const {code} = this
|
||||||
|
if (!!code) {
|
||||||
|
this.hideCode = Identity.hideId(code)
|
||||||
|
this.getIdCardInfo(code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static hideId(code) {
|
||||||
|
return code?.replace(/^(\d{10})\d{4}(.{4}$)/g, `$1${Array(5).join('*')}$2`)
|
||||||
|
}
|
||||||
|
|
||||||
|
getId18(code) {
|
||||||
|
if (code.length == 15) {
|
||||||
|
const id17 = code.substring(0, 6) + '19' + code.substring(6)
|
||||||
|
const parityBit = Check.getParityBit(id17)
|
||||||
|
return id17 + parityBit
|
||||||
|
} else if (code.length == 18) {
|
||||||
|
return code
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getIdCardInfo(idCardNo) {
|
||||||
|
this.birthday = Identity.getBirthday(idCardNo)
|
||||||
|
this.sex = Identity.getSex(idCardNo)
|
||||||
|
this.gender = PARAMS.genders[this.sex]
|
||||||
|
this.age = Identity.getAge(idCardNo)
|
||||||
|
this.areaId = Identity.getArea(idCardNo)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取性别
|
||||||
|
* @param code
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
static getSex(code) {
|
||||||
|
return (Number(code.substring(16, 17)) % 2).toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取年龄
|
||||||
|
* @param code
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
static getAge(code) {
|
||||||
|
const birthday = dayjs(code.substring(6, 14), 'YYYYMMDD')
|
||||||
|
return Math.ceil(dayjs.duration(dayjs().unix() - dayjs(birthday).unix(), 's').asYears())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取地区编码
|
||||||
|
* @param code
|
||||||
|
*/
|
||||||
|
static getArea(code) {
|
||||||
|
return code.substring(0, 6) + new Array(7).join(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取生日
|
||||||
|
*/
|
||||||
|
static getBirthday(code) {
|
||||||
|
return dayjs(code.substring(6, 14), 'YYYYMMDD').format("YYYY-MM-DD").replace('Invalid Date', '')
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 校验15位或18位的身份证号码 */
|
||||||
|
static check(idCardNo) {
|
||||||
|
// 15位和18位身份证号码的基本校验
|
||||||
|
const check = /^\d{15}|(\d{17}(\d|x|X))$/.test(idCardNo)
|
||||||
|
if (!check) return false
|
||||||
|
// 判断长度为15位或18位
|
||||||
|
if (idCardNo.length == 15) {
|
||||||
|
return Check.check15IdCardNo(idCardNo)
|
||||||
|
} else if (idCardNo.length == 18) {
|
||||||
|
return Check.check18IdCardNo(idCardNo)
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
35
wxmp/src/utils/moment.js
Normal file
35
wxmp/src/utils/moment.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import moment from 'dayjs'
|
||||||
|
import duration from 'dayjs/plugin/duration'
|
||||||
|
import updateLocale from 'dayjs/plugin/updateLocale'
|
||||||
|
import customParseFormat from 'dayjs/plugin/customParseFormat'
|
||||||
|
import 'dayjs/locale/zh-cn'
|
||||||
|
|
||||||
|
moment.locale('zh-cn')
|
||||||
|
moment.extend(updateLocale)
|
||||||
|
moment.extend(customParseFormat)
|
||||||
|
moment.extend(duration)
|
||||||
|
moment.updateLocale('zh-cn', {
|
||||||
|
weekdays: "星期日|星期一|星期二|星期三|星期四|星期五|星期六".split("|"),
|
||||||
|
meridiem(hour) {
|
||||||
|
let word = ""
|
||||||
|
if (hour < 6) {
|
||||||
|
word = "凌晨"
|
||||||
|
} else if (hour < 9) {
|
||||||
|
word = "早上"
|
||||||
|
} else if (hour < 12) {
|
||||||
|
word = "上午"
|
||||||
|
} else if (hour < 14) {
|
||||||
|
word = "中午"
|
||||||
|
} else if (hour < 17) {
|
||||||
|
word = "下午"
|
||||||
|
} else if (hour < 19) {
|
||||||
|
word = "傍晚"
|
||||||
|
} else if (hour < 22) {
|
||||||
|
word = "晚上"
|
||||||
|
} else {
|
||||||
|
word = "夜里"
|
||||||
|
}
|
||||||
|
return word;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export default moment
|
||||||
15
wxmp/src/utils/regular.js
Normal file
15
wxmp/src/utils/regular.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
export default {
|
||||||
|
phone: /^((0\d{2,3}-\d{7,8})|((13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}))$/,
|
||||||
|
password: /^(?=.*\d)(?=.*[a-zA-Z])(?=.*[~!@#$%^&*,.?_-])[\da-zA-Z~!@#$%^&*,.?_-]{8,16}$/,
|
||||||
|
money: /^([1-9]\d*|0)(\.\d{1,2})?$/,
|
||||||
|
area: {
|
||||||
|
village: /^\d{9}[^0]0{0,2}$/,
|
||||||
|
town: /^\d{6}[^0]0{0,2}000$/,
|
||||||
|
country: /^\d{4}[^0]0?0{6}$/,
|
||||||
|
city: /^\d{2}[^0]0?0{8}$/,
|
||||||
|
province: /^[^0]0?0{10}$/,
|
||||||
|
},
|
||||||
|
zh: /^[\u4e00-\u9fa5]+$/,
|
||||||
|
email: /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
|
||||||
|
ip: /((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))/
|
||||||
|
}
|
||||||
140
wxmp/src/utils/util.js
Normal file
140
wxmp/src/utils/util.js
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
import $dayjs from './moment'
|
||||||
|
import $dict from './dict'
|
||||||
|
import $qs from 'query-string'
|
||||||
|
import $coin from './coin'
|
||||||
|
import $reg from "./regular"
|
||||||
|
import identity from "./identity"
|
||||||
|
|
||||||
|
const $toast = (obj) => {
|
||||||
|
let params = {title: '', duration: 2000, icon: 'none'};
|
||||||
|
if (typeof obj == 'string') {
|
||||||
|
params.title = obj;
|
||||||
|
} else {
|
||||||
|
Object.assign(params, obj);
|
||||||
|
}
|
||||||
|
uni.showToast(params);
|
||||||
|
};
|
||||||
|
|
||||||
|
const $loading = (title = "加载中") => {
|
||||||
|
uni.showLoading({
|
||||||
|
title: title || '加载中',
|
||||||
|
mask: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const $hideLoading = () => {
|
||||||
|
uni.hideLoading();
|
||||||
|
};
|
||||||
|
|
||||||
|
const $dialog = {
|
||||||
|
alert: (params) => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
uni.showModal({
|
||||||
|
title: '温馨提示',
|
||||||
|
showCancel: false,
|
||||||
|
confirmColor: '#197DF0',
|
||||||
|
confirmText: params?.confirmButtonText || '确定',
|
||||||
|
...params,
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
confirm: (params) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
uni.showModal({
|
||||||
|
title: '温馨提示',
|
||||||
|
showCancel: true,
|
||||||
|
confirmColor: '#197DF0',
|
||||||
|
cancelText: params.cancelButtonText ? params.cancelButtonText : '取消',
|
||||||
|
confirmText: params.confirmButtonText ? params.confirmButtonText : '确定',
|
||||||
|
...params,
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
resolve();
|
||||||
|
} else if (res.cancel) {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const $linkTo = (url) => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const $formatName = (name) => {
|
||||||
|
if (name === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return name.substr(name.length - 2, name.length > 2 ? name.length - 1 : name.length);
|
||||||
|
};
|
||||||
|
|
||||||
|
const $previewImage = (list, index, urlName) => {
|
||||||
|
uni.previewImage({
|
||||||
|
current: list[index][urlName],
|
||||||
|
urls: list.map((v) => v[urlName])
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const $getUserProfile = () => {
|
||||||
|
return new Promise(function (resolve) {
|
||||||
|
wx.getUserProfile({
|
||||||
|
desc: '用于完善会员资料',
|
||||||
|
lang: 'zh_CN',
|
||||||
|
success: (data) => {
|
||||||
|
resolve(data);
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* 获取code
|
||||||
|
* @returns {Promise<unknown>}
|
||||||
|
*/
|
||||||
|
const $getLoginCode = () => {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
uni.login({
|
||||||
|
success: function (res) {
|
||||||
|
if (res.code) {
|
||||||
|
resolve(res);
|
||||||
|
} else {
|
||||||
|
reject(res);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fail: function () {
|
||||||
|
reject(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
$toast,
|
||||||
|
$loading,
|
||||||
|
$hideLoading,
|
||||||
|
$dialog,
|
||||||
|
$linkTo,
|
||||||
|
$formatName,
|
||||||
|
$previewImage,
|
||||||
|
$getUserProfile,
|
||||||
|
$dayjs,
|
||||||
|
$dict,
|
||||||
|
$getLoginCode,
|
||||||
|
$qs,
|
||||||
|
$coin,
|
||||||
|
$reg,
|
||||||
|
$ChID: identity
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user