1646 lines
63 KiB
Markdown
1646 lines
63 KiB
Markdown
# uni-app微信小程序----“起名”
|
||
|
||
## 第一章 简介
|
||
|
||
### 1-1 宝宝起名简介
|
||
|
||
> 来自给宝宝起名做的功课,了解一些国人在起名方面的讲究
|
||
|
||
#### 中国人起名有哪些讲究?
|
||
|
||
**首先得避讳;**
|
||
|
||
一避讳国讳;
|
||
|
||
二避讳帝王;
|
||
|
||
三避讳先贤;
|
||
|
||
四避讳先人;
|
||
|
||
五避讳虚拟人名;
|
||
|
||
六忌讳生僻字;
|
||
|
||
七避讳多音字;
|
||
|
||
**根据中国人文化传统起名**
|
||
|
||
三才五格法(通过笔画判定吉凶)
|
||
|
||
八字法(通过生辰判定五行盛衰)
|
||
|
||
寓意法(通过耳熟能详的美好诗句、成语组合起名)
|
||
|
||
|
||
|
||
通过这些方法达到数理得当、八字匹配、寓意美好、高端大气;
|
||
|
||
### 数理派
|
||
|
||
五格法:天格、人格、地格、外格和总格是笔画数来判定吉凶—判定标准为81数理
|
||
|
||
人格、地格、外格和总格
|
||
|
||
认为笔划全吉,人生就大吉
|
||
|
||
~~切记:全部测算需要繁体字~~
|
||
|
||
有算过命的人都会知道,当你把你的姓名生辰年月告诉给算命先生以后,算命先生就会根据你所提供的信息跟你简单地说一下你的天格多少,地格多少,等等。算命先生说的五格:天格,地格,人格,外格,总格分别是什么" 相信大部分人对此都不太了解他们口中所说的天格,地格是什么意思,接下来笔者就为各位朋友详细描述一下。
|
||
|
||
#### 天格
|
||
|
||
天格为五格之一,是姓氏格,因姓氏来源于祖先,古人将先人、君主比作天,故有关姓氏的数理称为天格。天格对人格有相当密切的关系及影响力。代表童少年运。
|
||
|
||
**计算方法**:复姓,合计姓氏之笔画;单姓,再加假添一数。若是单姓,其天格数理为姓的笔划数加1,例如:王,为四划,加1为5,其天数理为5。若是复姓,其天格数理即复姓的笔划数,而不必再加1。例如:司马,笔画为8,则其天书里为8。
|
||
|
||
#### 地格
|
||
|
||
地格为五格之一,由名组成,地格是前运格和基础运格,主管1-17岁之间的运势,代表少年时期,和人格有相当密切的关系。其数理吉凶,亦代表与子女、部属、晚辈的关系。代表前运。
|
||
|
||
**计算方法**:由名字全部笔画数构成,若是单名,则地格数理名字笔画加1,例如:王三,三,3画,加1为4,其地格数理为4;若是复姓,其地格数理的整个名字的笔划数。例如:王江海,江海,10画,其地格理数为10。
|
||
|
||
#### 人格
|
||
|
||
人格由姓与名字中的第一个字决定,主管17-32岁之间的运势,以主人之成就,能力、个性、境遇,作用力可影响人的一生,是人的中心主运,并且与天格、地格、外格均有相互的作用,是五格的重点
|
||
|
||
**计算方法**:人格:又称'主运',是整个姓名的中心点,人一生的命运,均由此人格推断。如果是单姓,姓名前两个字的原笔画相加,就是人格。比如王一智,4画的王加上1画的一等于5,那这个5就是人格。如果是复姓,则由复姓的总和数再加上姓名第三个字的笔画数,比如司马相如,15划的司马,再加上8画的相等于23,那23就是此名的人格。
|
||
|
||
#### 外格
|
||
|
||
外格代表副运或中年运,主管33-48岁之间的运势,代表着社交活动、人际关系、环境家居、同辈关系等,其数理吉凶与人格关系密切,相互作用力较大。代表副运。
|
||
|
||
**计算方法:**总格笔画数减去人格笔画数,如是单字名或单姓,再加一划。单姓单名:如“王石”这个名字,王为4画,“石”为5画,总格为9画,人格为9画,单姓单名,再加2画,外格为2画。单姓双名:如“关云长”这个名字,“关”为19画,“云”为12画,“长”为8画。总格为39画,39画减去人格31画,在加1,等于9画,外格之数为9画。复姓单名:如“司马懿”这个名字,“司”为5画,“马”为10画,“懿”为22画,相加为37画,37话减去人格笔画再加1,等于6画。司马懿的外格之数是6画。复姓复名的计算方法也是一样的。
|
||
|
||
#### 总格
|
||
|
||
总格是合计姓与名的总笔画数,主中年至晚年的命运,又称'后运'。总格代表其人之一生,总纳天地人三格之意义,但对于其人性格、职业、命运富于变化之中早年运缺乏明显的暗灵作用,但于其人成为一定之性向类型之后,即发生灵导吉凶作用。
|
||
|
||
**计算方法:**合计姓与名的总笔画数,主中年至晚年的命运,又称'后运'。如司马懿,总格数是5+10+22=37。刘江海,总格数是14+7+11=32。
|
||
|
||
|
||
|
||
#### 原理:81数理判定吉凶
|
||
|
||
第1数:(太极之数)太极之数,万物开泰,生发无穷,利禄亨通。 (吉)
|
||
|
||
第2数:(两仪之数)两仪之数,混沌未开,进退保守,志望难达。 (凶)
|
||
|
||
第3数:(三才之数)三才之数,天地人和,大事大业,繁荣昌隆。 (吉)
|
||
|
||
第4数:(四象之数)四象之数,待于生发,万事慎重,不具营谋。 (凶)
|
||
|
||
第5数:(五行之数)五行俱权,循环相生,圆通畅达,福祉无穷。 (吉)
|
||
|
||
第6数:(六爻之数)六爻之数,发展变化,天赋美德,吉祥安泰。 (吉)
|
||
|
||
第7数:(七政之数)七政之数,精悍严谨,天赋之力,吉星照耀。 (吉)
|
||
|
||
第8数:(八卦之数)八卦之数,乾坎艮震,巽离坤兑,无穷无尽。(半吉)
|
||
|
||
第9数:(大成之数)大成之数,蕴涵凶险,或成或败,难以把握。 (凶)
|
||
|
||
第10数:(终结之数)终结之数,雪暗飘零,偶或有成,回顾茫然。 (凶)
|
||
|
||
第11数:(旱苗逢雨)万物更新,调顺发达,恢弘泽世,繁荣富贵。 (吉)
|
||
|
||
第12数:(掘井无泉)无理之数,发展薄弱,虽生不足,难酬志向。 (凶)
|
||
|
||
第13数:(春日牡丹)才艺多能,智谋奇略,忍柔当事,鸣奏大功。 (吉)
|
||
|
||
第14数:(破兆)家庭缘薄,孤独遭难,谋事不达,悲惨不测。 (凶)
|
||
|
||
第15数:(福寿)福寿圆满,富贵荣誉,涵养雅量,德高望重。 (吉)
|
||
|
||
第16数:(厚重)厚重载德,安富尊荣,财官双美,功成名就。 (吉)
|
||
|
||
第17数:(刚强)权威刚强,突破万难,如能容忍,必获成功。 (半吉)
|
||
|
||
第18数:(铁镜重磨)权威显达,博得名利,且养柔德,功成名就。 (半吉)
|
||
|
||
第19数:(多难)风云蔽日,辛苦重来,虽有智谋,万事挫折。 (凶)
|
||
|
||
第20数:(屋下藏金)非业破运,灾难重重,进退维谷,万事难成。 (凶)
|
||
|
||
第21数:(明月中天)光风霁月,万物确立,官运亨通,大搏名利。 (吉)
|
||
|
||
第22数:(秋草逢霜)秋草逢霜,困难疾弱,虽出豪杰,人生波折。 (凶)
|
||
|
||
第23数:(壮丽)旭日东升,壮丽壮观,权威旺盛,功名荣达。(吉)
|
||
|
||
第24数:(掘藏得金)家门余庆,金钱丰盈,白手成家,财源广进。 (吉)
|
||
|
||
第25数:(荣俊)资性英敏,才能奇特,克服傲慢,尚可成功。 (半吉)
|
||
|
||
第26数:(变怪)变怪之谜,英雄豪杰,波澜重叠,而奏大功。 (凶)
|
||
|
||
第27数:(增长)欲望无止,自我强烈,多受毁谤,尚可成功。 (凶)
|
||
|
||
第28数:(阔水浮萍)遭难之数,豪杰气概,四海漂泊,终世浮躁。 (凶)
|
||
|
||
第29数:(智谋)智谋优秀,财力归集,名闻海内,成就大业。 (吉)
|
||
|
||
第30数:(非运)沉浮不定,凶吉难变,若明若暗,大成大败。 (半吉)
|
||
|
||
第31数:(春日花开)智勇得志,博得名利,统领众人,繁荣富贵。 (吉)
|
||
|
||
第32数:(宝马金鞍)侥幸多望,贵人得助,财帛如裕,繁荣至上。 (吉)
|
||
|
||
第33数:(旭日升天)旭日升天,鸾凤相会,名闻天下,隆昌至极。 (吉)
|
||
|
||
第34数:(破家)破家之身,见识短小,辛苦遭逢,灾祸至极。 (凶)
|
||
|
||
第35数:(高楼望月)温和平静,智达通畅,文昌技艺,奏功洋洋。 (吉)
|
||
|
||
第36数:(波澜重叠)波澜重叠,沉浮万状,侠肝义胆,舍己成仁。 (半吉)
|
||
|
||
第37数:(猛虎出林)权威显达,热诚忠信,宜着雅量,终身荣富。 (吉)
|
||
|
||
第38数:(磨铁成针)意志薄弱,刻意经营,才识不凡,技艺有成。 (半吉)
|
||
|
||
第39数:(富贵荣华)富贵荣华,财帛丰盈,暗藏险象,德泽四方。 (半吉)
|
||
|
||
第40数:(退安)智谋胆力,冒险投机,沉浮不定,退保平安。 (凶)
|
||
|
||
第41数:(有德)纯阳独秀,德高望重,和顺畅达,博得名利。此数为最大好运数。 (吉)
|
||
|
||
第42数:(寒蝉在柳)博识多能,精通世情,如能专心,尚可成功。 (凶)
|
||
|
||
第43数:(散财破产)散财破产,诸事不遂,虽有智谋,财来财去。 (凶)
|
||
|
||
第44数:(烦闷)破家亡身,暗藏惨淡,事不如意,乱世怪杰。 (凶)
|
||
|
||
第45数:(顺风)新生泰和,顺风扬帆,智谋经纬,富贵繁荣。 (吉)
|
||
|
||
第46数:(浪里淘金)载宝沉舟,浪里淘金,大难尝尽,大功有成。 (凶)
|
||
|
||
第47数:(点石成金)花开之象,万事如意,祯祥吉庆,天赋幸福。 (吉)
|
||
|
||
第48数:(古松立鹤)智谋兼备,德量荣达,威望成师,洋洋大观。 (吉)
|
||
|
||
第49数:(转变)吉临则吉,凶来则凶,转凶为吉,配好三才。 (半吉)
|
||
|
||
第50数:(小舟入海)一成一败,吉凶参半,先得庇荫,后遭凄惨。 (半吉)
|
||
|
||
第51数:(沉浮)盛衰交加,波澜重叠,如能慎始,必获成功。 (半吉)
|
||
|
||
第52数:(达眼)卓识达眼,先见之明,智谋超群,名利双收。 (吉)
|
||
|
||
第53数:(曲卷难星)外祥内患,外祸内安,先富后贫,先贫后富。 (凶)
|
||
|
||
第54数:(石上栽花)石上栽花,难得有活,忧闷烦来,辛惨不绝。 (凶)
|
||
|
||
第55数:(善恶)善善得恶,恶恶得善,吉到极限,反生凶险。 (半吉)
|
||
|
||
第56数:(浪里行舟)历尽艰辛,四周障碍,万事龃龌,做事难成。 (凶)
|
||
|
||
第57数:(日照春松)寒雪青松,夜莺吟春,必遭一过,繁荣白事。 (吉)
|
||
|
||
第58数:(晚行遇月)沉浮多端,先苦后甜,宽宏扬名,富贵繁荣。 (半吉)
|
||
|
||
第59数:(寒蝉悲风)寒蝉悲风,意志衰退,缺乏忍耐,苦难不休。 (凶)
|
||
|
||
第60数:(无谋)无谋之人,漂泊不定,晦暝暗黑,动摇不安。 (凶)
|
||
|
||
第61数:(牡丹芙蓉)牡丹芙蓉,花开富贵,名利双收,定享天赋。 (吉)
|
||
|
||
第62数:(衰败)衰败之象,内外不和,志望难达,灾祸频来。 (凶)
|
||
|
||
第63数:(舟归平海)富贵荣华,身心安泰,雨露惠泽,万事亨通。 (吉)
|
||
|
||
第64数:(非命)骨肉分离,孤独悲愁,难得心安,做事不成。 (凶)
|
||
|
||
第65数:(巨流归海)天长地久,家运隆昌,福寿绵长,事事成就。 (吉)
|
||
|
||
第66数:(岩头步马)进退维谷,艰难不堪,等待时机,一跃而起。 (凶)
|
||
|
||
第67数:(顺风通达)天赋幸运,四通八达,家道繁昌,富贵东来。 (吉)
|
||
|
||
第68数:(顺风吹帆)智虑周密,集众信达,发明能智,拓展昂进。 (吉)
|
||
|
||
第69数:(非业)非业非力,精神迫滞,灾害交至,遍偿痛苦。 (凶)
|
||
|
||
第70数:(残菊逢霜)残菊逢霜,寂寞无碍,惨淡忧愁,晚景凄凉。 (凶)
|
||
|
||
第71数:(石上金花)石上金花,内心劳苦,贯彻始终,定可昌隆。 (半吉)
|
||
|
||
第72数:(劳苦)荣苦相伴,阴云覆月,外表吉祥,内实凶祸。 (半吉)
|
||
|
||
第73数:(无勇)盛衰交加,徒有高志,天王福祉,终世平安。 (半吉)
|
||
|
||
第74数:(残菊经霜)残菊经霜,秋叶寂寞,无能无智,辛苦繁多。 (凶)
|
||
|
||
第75数:(退守)退守保吉,发迹甚迟,虽有吉象,无谋难成。 (凶)
|
||
|
||
第76数:(离散)倾覆离散,骨肉分离,内外不和,虽劳无功。 (凶)
|
||
|
||
第77数:(半吉)家庭有悦,半吉半凶,能获援护,陷落不幸。 (半吉)
|
||
|
||
第78数:(晚苦)祸福参半,先天智能,中年发达,晚景困苦。 (凶)
|
||
|
||
第79数:(云头望月)云头望月,身疲力尽,穷迫不伸,精神不定。 (凶)
|
||
|
||
第80数:(遁吉)辛苦不绝,早入隐遁,安心立命,化凶转吉。 (凶)
|
||
|
||
第81数:(万物回春)最吉之数,还本归元,吉祥重叠,富贵尊荣。 (吉)
|
||
|
||
### 八字派
|
||
|
||
根据出生年月判定天地人三才五行相生,判定喜用神,补到先天八字命盘欠缺!
|
||
|
||
生辰八字中的天干地支分别对应五行中的五个元素,如天干的甲、乙和地支的寅、卯属性为木,天干中的丙、丁和地支中的巳、午属性为火等。根据这个规律,可以推算出宝宝的五行为:金木土木木土木水(庚寅己卯甲戌甲子)。
|
||
|
||
一般来说,生辰八字中所含的金、木、水、火、土的数量,某一个属性有两个相同的,就是适中的,多于两个为“旺”,少于两个为“弱”,没有的为缺。缺和弱的需要补足,过旺过强则需要抑制。
|
||
|
||
通过分析这个宝宝的八字五行:金木土木木土木水(4木,0火,2土,1金,1水),可以明显看出:五行木旺、缺火。因此可以判断出这个宝宝的八字喜“火”,起名最好用五行属性为“火”的字。
|
||
|
||
#### 计算方法:天干地支法
|
||
|
||
八字命盘从阴阳干支三合历取得。上排是天干,由五行「金水木火土」轮流排列。下排是地支,用十二生肖顺序排列。十二生肖可转换成五行。
|
||
|
||
#### 六十甲子表:
|
||
|
||
| 甲子 | 乙丑 | 丙寅 | 丁卯 | 戊辰 | 已巳 | 庚午 | 辛未 | 壬申 | 癸酉 |
|
||
| ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- |
|
||
| 甲戌 | 乙亥 | 丙子 | 丁丑 | 戊寅 | 已卯 | 庚辰 | 辛巳 | 壬午 | 癸未 |
|
||
| 甲申 | 乙酉 | 丙戌 | 丁亥 | 戊子 | 已丑 | 庚寅 | 辛卯 | 壬辰 | 癸巳 |
|
||
| 甲午 | 乙未 | 丙申 | 丁酉 | 戊戌 | 已亥 | 庚子 | 辛丑 | 壬寅 | 癸卯 |
|
||
| 甲辰 | 乙巳 | 丙午 | 丁未 | 戊申 | 已酉 | 庚戌 | 辛亥 | 壬子 | 癸丑 |
|
||
| 甲寅 | 乙卯 | 丙辰 | 丁巳 | 戊午 | 已未 | 庚申 | 辛酉 | 壬戌 | 癸亥 |
|
||
|
||
#### 六十甲子纳音五行如下:
|
||
|
||
|
||
甲子乙丑海中金,甲午乙未沙中金
|
||
|
||
丙寅丁卯炉中火,丙申丁酉山下火
|
||
|
||
戊辰己巳大林木,戊戌己亥平地木
|
||
|
||
庚午辛未路旁土,庚子辛丑壁上土
|
||
|
||
壬申癸酉剑锋金,壬寅癸卯金泊金
|
||
|
||
甲戌乙亥山头火,甲辰乙巳覆灯火
|
||
|
||
丙子丁丑涧下水,丙午丁未天河水
|
||
|
||
戊寅己卯城头土,戊申己酉大驿土
|
||
|
||
庚辰辛巳白腊金,庚戌辛亥钗钏金
|
||
|
||
壬午癸未杨柳木,壬子癸丑桑柘木
|
||
|
||
甲申乙酉泉中水,甲寅乙卯大溪水
|
||
|
||
丙戌丁亥屋上土,丙辰丁巳沙中土
|
||
|
||
戊子己丑霹雳火,戊午己未天上火
|
||
|
||
庚寅辛卯松柏木,庚申辛酉石榴木
|
||
|
||
壬辰癸巳长流水,壬戌癸亥大海水
|
||
|
||
#### 天干五行和地支五行对照表
|
||
|
||
天干:,甲-木,乙-木,丙-火,丁-火,戊-土,己-土,庚-金,辛-金,壬-水,癸-水
|
||
地支:子-水,丑-土,寅-木,卯-木,辰-土,巳-火,午-火,未-土,申-金,酉-金,戌-土,亥-水
|
||
|
||
八字根据 输入公历日期,查出你的出生年,月,日的干支四柱,从而判断八字属性:
|
||
|
||
![image-20200314142027464](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200314142027464.png)
|
||
|
||
####
|
||
|
||
#### **年柱计算方法:**
|
||
|
||
##### 最简单的是查表地表法:
|
||
|
||
记年60年是一个循环,记月60月是一个循环,记日60日是一个循环,记时60时是一个循环。年月日时各用两个字表示,这就是人们通常说的“生辰八字”。
|
||
|
||
1、比如,记住几个特殊的年份如1984年为甲子年,类推1924,1864,1804,……均为甲子年。提到的壬戌是第59顺位,那么用甲子年份加上59减1得到的1982,1922,1862,1802……都是壬戌年!
|
||
|
||
|
||
|
||
2、比如,《辛亥革命》的辛亥年是1911年(48号干支),《戊戌变法》的戊戌年为35号干支,比辛亥年早13年,则“1911-13=1898”故《戊戌变法》是1898年。
|
||
|
||
|
||
|
||
3、比如,2008年:2008-3=2005,2005&pide;60,余数为25,查六十年甲子(干支表)25号干支,得知是戊子年。
|
||
|
||
|
||
|
||
4、比如,求1991年干支:1991&pide;60=33余11,年干支序号数=11-3=8。查干支表知该年为辛未年。
|
||
|
||
|
||
|
||
(注意:年干支的是以立春为分界的,正月立春以后出生的,用本年干支;在立春前出生的,用上一年的干支)
|
||
|
||
##### 其次是计算法:
|
||
|
||
方法一:
|
||
|
||
首先要能记住十大天干和十二地支,十天干:甲、乙、丙、丁、戊、己、庚、辛、壬、癸;十二地支:子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥;
|
||
|
||
天干地支纪年法首先是天干在前,地支在后,比如今年2005就为-乙酉年。
|
||
|
||
|
||
|
||
天干算法:
|
||
|
||
4、 5、 6、 7、 8、 9、 0、 1、 2、 3 对应的十天干就是
|
||
|
||
甲、乙、丙、丁、戊、己、庚、辛、壬、癸,
|
||
|
||
数字为年代的最后的一位数字,比如2005年,最后一位是5,对应的天干就是乙;
|
||
|
||
|
||
|
||
地支的算法:用年代数除以12,后面的余数就代表某个地支,
|
||
|
||
余数分别为:4、 5、 6、 7、 8、 9、 10、 11、 0(能整除)、1、 2、3,
|
||
|
||
代表地支为:子、丑、寅、卯、辰、巳、午、 未、 申、酉、戌、亥,
|
||
|
||
比如2005年为例:年代末尾数为5,对应的天干为乙,2005除以12,余数为1,对应的地支为酉,所以2005年为乙酉年。
|
||
|
||
|
||
|
||
方法二:
|
||
|
||
对应数字:1、 2、 3、 4、 5、 6、 7、 8、 9、 0
|
||
|
||
相应天干:甲、乙、丙、丁、戊、己、庚、辛、壬、癸
|
||
|
||
对应数字:1、 2、 3、 4、 5、 6、 7、 8、 9、 10、 11、 0
|
||
|
||
相应地支:子、丑、寅、卯、辰、巳、午、未、 申、 酉、 戌、 亥
|
||
|
||
公元年份-3,除以10得余数可得天干,如1984年,(1984-3)|10=1所以天干为甲;
|
||
|
||
公元年份-3,除以12得余数可得地支,如1984年,(1984-3)|12=1所以地支为子;
|
||
|
||
所以公元1984年为甲子年。
|
||
|
||
|
||
|
||
方法三:
|
||
|
||
用一个你知道的年份的天干地支来推算,比如用2006年算1955年的天干地支,先要知道2006年是丙戌年,用2006-1955=51,再用51除以10,余数为1,表明天干是丙往前推一位,答案是乙,接着用51除以12,余数为3,表明地支是戌往前推三位,答案是未,那么1955年就是乙未年。
|
||
|
||
#### 月柱计算方法:
|
||
|
||
月的地支是固定不变的:正月是寅,二月是卯,三月是子,依次类推......
|
||
|
||
月的天干记忆比较简单,只要在你年干的基础上记住几句歌诀便可以了:
|
||
|
||
甲己之年丙做首;乙庚之年卯为头;
|
||
|
||
丙辛必定寻庚起;丁壬壬位顺流行;
|
||
|
||
还有戊癸何方觅,甲定之上好追求。
|
||
|
||
意思就是说,若遇甲或己的年份,正月是丙寅;遇上乙或庚之年,正月为戊寅;遇上丙或辛之年,正月为庚寅;遇上丁或壬之年,正月为壬寅;遇上戊或癸之年,正月为甲寅。依照正月之干支,其余月份按干支推算即可。有表如下:
|
||
|
||
年 份一月 二月 三月 四月 五月 六月 七月 八月 九月 十月 十一月 十二月
|
||
|
||
甲、巳丙寅 丁卯 戊辰 己巳 庚午 辛未 壬申 癸酉 甲戌 乙亥 丙子 丁丑
|
||
|
||
乙、庚戊寅 己卯 庚辰 辛巳 壬午 癸未 甲申 乙酉 丙戌 丁亥 戊子 己丑
|
||
|
||
丙、辛庚寅 辛卯 壬辰 癸巳 甲午 乙未 丙申 丁酉 戊戌 己亥 庚子 辛丑
|
||
|
||
丁、壬壬寅 癸卯 甲辰 乙巳 丙午 丁未 戊申 己酉 庚戌 辛亥 壬子 癸丑
|
||
|
||
戊、癸甲寅 乙卯 丙辰 丁巳 戊午 己未 庚申 辛酉 壬戌 癸亥 甲子 乙丑
|
||
|
||
| 年 份 | 一月 | 二月 | 三月 | 四月 | 五月 | 六月 | 七月 | 八月 | 九月 | 十月 | 十一月 | 十二月 |
|
||
| ------ | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ------ | ------ |
|
||
| 甲、巳 | 丙寅 | 丁卯 | 戊辰 | 己巳 | 庚午 | 辛未 | 壬申 | 癸酉 | 甲戌 | 乙亥 | 丙子 | 丁丑 |
|
||
| 乙、庚 | 戊寅 | 己卯 | 庚辰 | 辛巳 | 壬午 | 癸未 | 甲申 | 乙酉 | 丙戌 | 丁亥 | 戊子 | 己丑 |
|
||
| 丙、辛 | 庚寅 | 辛卯 | 壬辰 | 癸巳 | 甲午 | 乙未 | 丙申 | 丁酉 | 戊戌 | 己亥 | 庚子 | 辛丑 |
|
||
| 丁、壬 | 壬寅 | 癸卯 | 甲辰 | 乙巳 | 丙午 | 丁未 | 戊申 | 己酉 | 庚戌 | 辛亥 | 壬子 | 癸丑 |
|
||
| 戊、癸 | 甲寅 | 乙卯 | 丙辰 | 丁巳 | 戊午 | 己未 | 庚申 | 辛酉 | 壬戌 | 癸亥 | 甲子 | 乙丑 |
|
||
|
||
#### 日柱计算方法:
|
||
|
||
1.已知某年元旦干支,推算日干日支
|
||
|
||
公式:日干代数=元旦天干代数+所求日数±按月加减数-天干周转数。
|
||
|
||
日支代数=元旦地支代数+所求日数±按月加减数-地支周转数。
|
||
|
||
说明:1.按月加减数是根据日数与六十环周推算出来的。
|
||
|
||
2.各月干支加减表如下图。
|
||
|
||
|
||
|
||
举例:已知1981年的元旦干支为“己卯”,求该年8月14日的日干支。
|
||
|
||
解答:1981为平年,推算日干支代数,
|
||
|
||
日干代数=己6+14+1-2×10=1(甲),
|
||
|
||
日支代数=卯4+14+7-2×12=1(子),
|
||
|
||
故1981年8月14日的日干支为甲子。
|
||
|
||
|
||
|
||
2.已知某年元旦干支,推求所求年的元旦干支,再推求该年的日干支
|
||
|
||
公式:①平年求下一年的元旦干支=平年的元旦干支的基数+5
|
||
|
||
(因为平年的元旦到下一年的元旦,干支数差5天)
|
||
|
||
②闰年求下一年的元旦干支=闰年的元旦干支的基数+6
|
||
|
||
(因为闰年的元旦到下一年的元旦,干支数差6天)
|
||
|
||
|
||
|
||
举例:已知1980年的元旦干支是癸酉,求1981年的元旦干支。
|
||
|
||
解答:1980年为闰年,推算日干支代数,
|
||
|
||
日干代数=癸10+6-10=6(己),
|
||
|
||
日支代数=酉10+6-12=4(卯),
|
||
|
||
故1981年的元旦干支为己卯。
|
||
|
||
3.已知某年某日的日干支,求该年或他年的日干支。
|
||
|
||
步骤:①先求日总数;②总数的个位数(个位数为0则取10),作为顺数日干的根据,按值顺数即为所求日干;③总数除以12的余数(能整除则取12),作为顺数日支的依据,按值顺数即为所求日支。
|
||
|
||
|
||
|
||
举例:已知1988年元月4日为“戊午”,求1988年8月23日干支。
|
||
|
||
解答:①求日总数
|
||
|
||
元月 2月 3月 4月 5月 6月 7月 8月
|
||
|
||
28 + 29 + 31 + 30 + 31 + 30 + 31 + 23 = 233天
|
||
|
||
②总数个位数推日干
|
||
|
||
个位数为3,从戊推,戊→己→庚,故日干为庚。
|
||
|
||
③总数除以12的余数推日支
|
||
|
||
233&pide;12=19······5,从午推,午→未→申→酉→戌,故日支为戌。
|
||
|
||
故8月23日干支为庚戌。
|
||
|
||
#### 时干支的计算方法:
|
||
|
||
|
||
|
||
每日十二时辰与十二地支相配是固定不变的,因一天起于夜半的子时,故计算时亦从子时起,然后即顺排下去即知一天的时辰干支。有日上起时歌诀如下:
|
||
|
||
甲己还加甲,乙庚丙作初,丙辛生戊子,
|
||
|
||
丁壬庚子头,戊癸起壬子,周而复始求。
|
||
|
||
甲己起甲子:甲日、己日夜半的子时起于甲子时,顺推乙丑等。
|
||
|
||
乙庚起丙子:乙日、庚日夜半的子时起于丙子时,顺推乙丑等。
|
||
|
||
丙辛起戊子:丙日、辛日夜半的子时起于戊子时,顺推乙丑等。
|
||
|
||
丁壬起庚子:丁日、壬日夜半的子时起于庚子时,顺推乙丑等。
|
||
|
||
戊癸起壬子:戊日、癸日夜半的子时起于壬子时,顺推乙丑等。
|
||
|
||
|
||
|
||
举例:求癸日的6点的时干支。
|
||
|
||
解答:癸日起壬子,6点为卯时,从子时至卯时推四位,所以时干从壬开始推四位:壬、癸、甲、乙。
|
||
|
||
八字分类一共720*720=518400个
|
||
|
||
大家知道,四柱八字,男女断法不同,起大运方法不同,这样一个四柱八字又会生出两种组合,即四柱八字组合数乘以男女,即518400*2=1036800个
|
||
|
||
### 寓意派
|
||
|
||
根据小孩出生时间-地点,配合寓意良好的的诗词提字组合!
|
||
|
||
|
||
|
||
### 1-2 小程序简介
|
||
|
||
宝宝在线起名一直是中国人的刚需,与其路边寻找大师,不如求教线上业务
|
||
|
||
目前只在淘宝搜索:发现营业额极高,那如果用一个小程序将各大派系的起名逻辑整合上线,就能帮助大家在起名的时候省下一笔奶粉钱!
|
||
|
||
![image-20200305151834887](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200305151834887.png)
|
||
|
||
![image-20200305151850634](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200305151850634.png)
|
||
|
||
|
||
|
||
## 第二章 uni-app了解下
|
||
|
||
### 2-1 uni-app安装及目录介绍
|
||
|
||
#### 下载hbuilderx
|
||
|
||
要讲UNI-APP,不得不介绍dcloud旗下一款轻量级ide编辑器hbuilderx
|
||
|
||
下载地址dcloud.io官网下载
|
||
|
||
hx mac和win之间分为标准和APP版
|
||
|
||
标准版需要自己安装插件,app开发版已经把app开发常用的插件预先集成,开箱即可用
|
||
|
||
#### UNI-APP有两种创建方式
|
||
|
||
使用 vue-cli 脚手架 创建 uni-app
|
||
|
||
| cli创建UNI-APP目录名称 | 解析 |
|
||
| ---------------------- | ------------------------------------------------------------ |
|
||
| dist ->build | 存放通过build编译的各个平台的代码,如mp-weixin |
|
||
| node_modules | 项目依赖包模块 |
|
||
| public | 放置的为公共文件,比如index.html文件,为项目的生成模板,我们写的vue的代码,在webpack打包项目的时候,最后都会基于该模板转换为浏览器可读的三大件:html+javascript+css |
|
||
| src | 存放通过HBuilderX可视化界面创建的的所有目录,为源码目录 |
|
||
| .gitignore | git上传需要忽略的文件格式 |
|
||
| babel.config.js | ES6语法编译配置 |
|
||
| package.json | 项目基本信息 |
|
||
| package-lock.json | 锁定安装时的包的版本号,并且需要上传到git,以保证其他人在npm install时大家的依赖能保证一致 |
|
||
| postcss.config.js | postcss-loader 的配置文件名,通过js对 CSS 进行处理 |
|
||
| README.md | 项目说明 |
|
||
|
||
|
||
|
||
| **pages** | 业务页面文件存放的目录 |
|
||
| ------------- | ------------------------------------------------------------ |
|
||
| **static** | 存放应用引用静态资源(如图片、视频等)的地方,注意:静态资源只能存放于此 |
|
||
| app.vue | 应用配置,用来配置App全局样式以及监听生命周期 |
|
||
| main.js | Vue初始化入口文件 |
|
||
| manifest.json | 配置应用名称、appid、logo、版本等打包信息 |
|
||
| pages.json | 配置页面路由、导航条、选项卡等页面类信息 |
|
||
| uni.scss | 全局样式 |
|
||
|
||
|
||
|
||
### 2-2 uni-app配置
|
||
|
||
|
||
|
||
uni-app配置项目目录和微信小程序的目录基本相同
|
||
|
||
mainfest.json
|
||
|
||
主要作用配置应用名称、appid、logo、版本等打包信息
|
||
|
||
appid是微信小程序身份唯一标识
|
||
|
||
appid,以微信小程序为例子,
|
||
|
||
进入公众平台
|
||
|
||
pages.json
|
||
|
||
配置页面路由、导航条、tabbar选项卡等页面类信息
|
||
|
||
当我们在微信小程序 json 中设置 backgroundColor 时,实际在电脑的模拟器中根本看不到效果,
|
||
|
||
窗体下拉刷新或上拉加载时露出的背景
|
||
|
||
|
||
|
||
## 第三章 整体设计
|
||
|
||
### 3-1 api接口设计
|
||
|
||
什么是前后端分离?
|
||
|
||
前后端分离,就是在对前端开发人员和后端开发人员的工作进行解耦,尽量减少他她们之间的交流成本,帮助他她们更能专注于自己擅长的工作。
|
||
|
||
前端web 框架 vue \react \angular
|
||
|
||
安卓端
|
||
|
||
ios端
|
||
|
||
小程序端
|
||
|
||
pwa
|
||
|
||
本项目是一款基于 SpringBoot 的 Api 服务器脚手架。服务端基础通用框架提取,配以详细的说明文档,针对 Restful 风格 API 服务器,降低学习成本,提高开发效率
|
||
|
||
设计接口是一件容易的事,也是件困难的事。设计接口每个人都会,每个人都能设计,也由此产生了各种各样的理念的接口。工作这么多年,我也很有感悟。很多人会说,设计接口多么简单,只要命名好,然后联调通了,上线可以调用就行了。特别是非互联网行业的人,这里没有歧视的意思。因为互联网行业和传统行业太多不一致性决定了这种思想的产生。
|
||
|
||
|
||
|
||
**通过不同的method(get\post\put\delete)来进行crud**
|
||
|
||
**格式{ "data": 返回数据, "code": 状态码, "msg": "返回描述"}**
|
||
|
||
### 3-2 mysql数据库搭建
|
||
|
||
本机vmware搭建centos7环境
|
||
|
||
使用docker安装mysql8
|
||
|
||
### 3-3 mysql数据库创建和设计规范
|
||
|
||
> #### **《mysql设计规范》**
|
||
>
|
||
> 数据结构设计:逻辑设计 –> 物理设计
|
||
> 实际工作中:逻辑设计 + 物理设计
|
||
> 物理设计:表名,字段名,字段类型
|
||
> 磁盘IO和操作系统类型,对mysql的性能是非常大的
|
||
>
|
||
> ##### 一. 数据库命名规范
|
||
>
|
||
> 所有的数据库对象名称必须使用小写字母并用下划线表示,因为默认情况下,mysql对大小写敏感,mysql数据库本质上是linux系统下的一个文件,而linux系统是大小写敏感的
|
||
> 所有数据库对象名称禁止使用mysql保留关键字
|
||
> 数据库对象的命名要能做到见名知意,并且最好不要超过32个字符。太长不方便使用,并且会在传输时增加网络开销
|
||
> 临时表必须以tmp_为前缀并以日期为后缀
|
||
> 备份表必须以bak_为前缀并以日期为后缀
|
||
> 所有存储相同数据的列名和列类型必须一致,比如user表中的id和order表中的user_id
|
||
>
|
||
> ##### 二. 数据库基本设计规范
|
||
>
|
||
> 所有表必须使用Innodb存储引擎
|
||
> 极少数特殊业务需求除外
|
||
> Innodb引擎是5.6之后的默认存储引擎;mysql5.5之前使用Myisam(默认存储引擎)
|
||
> Innodb优点:支持事务,行级锁,更好的恢复性,高并发下性能更好
|
||
> 数据库和表的字符集统一使用UTF-8
|
||
> 如果要存储一些如表情符号的,还需使用UTF-8的拓展字符集
|
||
> 数据库,表,字段字符集一定要统一,统一字符集可以避免由于字符集转换产生的乱码
|
||
> 在mysql中UTF-8字符集,汉字占3字节,ASCII码占1字节
|
||
> 所有表和字段都需要添加注释
|
||
> 从一开始就进行数据字典的维护
|
||
> 即数据库说明文档
|
||
> 尽量控制单表数据量大小,
|
||
> 建议控制在500万以内,虽然500万并不是mysql的数据库限制,但是会给修改表结构,备份,恢复带来很大困难。
|
||
> 单表可存储数据量大小取决于存储设置和文件系统
|
||
> 想减少单表数据量:历史数据归档(常见于日志表),分库分表(常见于业务表),分区表
|
||
> 建议不要使用mysql分区表,因为分区表在物理上表现为多个文件,在逻辑上表现为一个表。如果一定要分区,请谨慎选择分区键,跨分区查询效率比查询大数据量的单表查询效率更低
|
||
> 建议采物理分表的方式管理大数据,但是对应用程序的开发要求和复杂度更高
|
||
> 尽量做到冷热数据分离,减少表的宽度(字段数)
|
||
> 减少磁盘IO,保证热数据的内存缓存命中率,更有效的利用缓存,避免读入无用的冷数据
|
||
> 这样的话,就要对表的列进行拆分,将经常使用的列放到一个表中,可以避免过多的关联操作,也可以提高查询性能
|
||
> 禁止在表中建立预留字段
|
||
> 预留字段很难做到见名知义,预留字段无法确定存储的数据类型,后期如果修改字段类型,会对全表锁定,严重影响数据库的并发性
|
||
> 对目前mysql来说,修改一个字段的成本要远远大于增加一个字段的成本
|
||
> 禁止在数据库中存储图片,文件等二级制数据
|
||
> 这类数据如果要存,就得使用blog或者text这样的大字段加以存储,会影响数据库的性能
|
||
> 文件这种通常所占数据容量很大,会在短时间内造成数据库文件的快速增长,而数据库在读取数据时,会进行大量的随机IO操作,如果数据文件过大,IO操作会非常耗时,从而影响数据库性能
|
||
> 正确做法是将这类数据存储在文件服务器中,而数据库只村存储地址信息
|
||
> 禁止在线上做数据库压力测试
|
||
> 会对正常业务造成影响,也会产生很多垃圾数据
|
||
> 建议建立专门的压力测试数据库,进行测试,然后对比测试服务器和线上服务器的硬件环境,评估线上数据库的性能
|
||
> 禁止从开发环境,测试环境直连生产环境数据库
|
||
>
|
||
> ##### 三. 索引设计规范(Innodb中主键实质上是一个索引)
|
||
>
|
||
> 限制每张表上索引数量,建议单表不超过5个索引。索引并不是越多越好,可以提高查询效率,但是会降低插入和更新的效率。甚至在一些情况下,还会降低查询效率,因为mysql优化器在选择如何优化查询时,会根据统计信息,对每一个可用索引来进行评估,以生成一个最好的执行计划,如果同时有很多索引都可以用于查询,就会增加mysql查询优化器生成查询计划的时间。
|
||
> 每个Innodb表都必须有一个主键。Innodb是一种索引索引组织表,是指数据存储的逻辑顺序和索引的顺序是相同,Innodb是按照主键索引的顺序来组织表的,因此,每个Innodb表都必须要有一个主键,如果我们没有指定主键,那么Innodb会优先选择表中第一个非空唯一索引来作为主键,如果没有这个索引,那么Innodb会自动生成一个占6字节的主键,而这个主键的性能并不是最好。
|
||
> 不使用更新频繁的列作为主键,不使用多列联合主键。因为Innodb是一种索引索引组织表,如果主键上的值频繁更新,就意味着数据存储的逻辑顺序频繁变动,必然会带来大量的IO操作,降低数据库性能。
|
||
> 不要使用uuid,md5,hash,字符串列作为主键。因为这种主键不能保证主键的值是顺序增长的,如果后来的主键值在已有主键值的中间段,那么这个主键插入的时候,会将所有主键值大于它的列都向后移。
|
||
> 最好选择能保证值的顺序为顺序增长的列为主键。并且数据不能重复,建议用mysql自增id建立主键
|
||
> 面试问题1: 要在哪些列上建立索引?
|
||
> 在select,delete,update的where从句中的列
|
||
> 包含在order by,group by,distinct字段中的列
|
||
> 多表join的关联列:mysql对关联操作的处理方式只有一种,那就是嵌套循环的关联方式,所以这种操作的性能对关联列上的索引的依赖性很大
|
||
> 面试问题2: 复合索引,如何选择索引列的顺序?
|
||
> 从左到右的顺序来使用的
|
||
> 区分度(列中group by的数目和此列总行数的比值趋近于1)最高的列放在联合索引的最左侧
|
||
> 在区分度差不多的情况下,尽量吧字段长度小的放在联合索引的最左侧,因为同样的行数,字段小的文件也小,读取时IO性能更优
|
||
> 使用最频繁的列放在联合索引的左侧,这样的话,可以较少地建立索引就能满足需求
|
||
> 避免建立冗余索引和重复索引
|
||
> 对于频繁的查询优先使用覆盖索引
|
||
> 就是包含了所有查询字段的索引,这样可以避免Innodb表进行索引的二次查找,并可以把随机IO变为顺序IO提高查询效率
|
||
> 尽量避免使用外键
|
||
> mysql和别的数据库不同,会自动在外键上建立索引,会降低数据库的写性能
|
||
> 建议不使用外键约束,但是一定要在表与表之间的关联键上建立索引,虽然外键是为了保证数据的完整性,但是最好在代码中去保证。
|
||
>
|
||
> ##### 四. 字段设计规范
|
||
>
|
||
> 优先选择符合存储需要的最小的数据类型
|
||
> 尽量将字符串转化为数字类型存储:如将ip存储为数字:inet_aton(‘255.255.255.255’) = 4294967295 ,反之, inet_ntoa(4294967295) = ‘255.255.255.255’
|
||
> 对于非负整型数据,优先使用无符号整型来存储,如:id,age,无符号相对于有符号,可以多出一倍的存储空间
|
||
> mysql中,varchar(n)中n表示字符数而不是字节数
|
||
> 避免使用text,blog来存储字段,这种类型只能使用前缀索引,如果非要使用,建议将这种数据分离到单独的拓展表中
|
||
> 避免使用enum类型。枚举本身是一个字符串类型,但是内部确是用正数类型来存储的,所以最多可存储65535种不同的值,修改的话必须使用alter语句,直接修改元数据,有操作风险;order by效率低,必须转换并无法使用索引,禁止使用数值作为enum值,因为enum本身是索引顺序存储的,会造成逻辑混淆
|
||
> 尽可能把所有列定义为not null。
|
||
> 索引null列需要额外的空间来保存,占更多空间
|
||
> 进行比较和计算时,对null值作特别的处理,可能造成索引失效
|
||
> 禁止使用字符串来存储日期型数据。
|
||
> 无法使用日期函数计算比较
|
||
> 字符串存储要占更多的内存空间,datetime(8字节)和timestamp(本身是以int存储,占4字节,范围:1970-01-01 00:00:01到2038-01-19 03:14:07)
|
||
> 财务相关数据,使用decimal类型 (精准浮点类型,在计算时不丢失精度)。
|
||
>
|
||
> ##### 五. SQL开发规范
|
||
>
|
||
> 建议使用预编译语句(prepareStatment)进行数据库操作
|
||
> 可以同步执行预编译计划,减少预编译时间
|
||
> 可以有效避免动态sql带来的SQL注入的问题
|
||
> 只传参数,一次解析,多次使用,比传递sql语句更高效
|
||
> 避免数据类型的隐式转换
|
||
> 一般出现在where从句中,会导致索引失效,如:select id,name from user where id = ‘12’;
|
||
> 充分利用已存在的索引
|
||
> 避免使用双%的查询条件,不走索引
|
||
> 一个SQL只能利用到复合索引中的一列进行范围查询
|
||
> 使用left join或not exists来优化not in操作
|
||
> 程序连接不同的数据库使用不同的账号,禁止跨库查询
|
||
> 为数据库迁移和分库分表留出余地
|
||
> 降低业务耦合度
|
||
> 避免权限过大而产生的安全风险
|
||
> 禁止使用select * 来查询,必须用字段名
|
||
> 可能会消耗更多的cpu和IO以及网络资源
|
||
> 无法使用覆盖索引
|
||
> 可以减少表结构变更对已有程序的影响
|
||
> 禁止使用不含字段列表的insert语句。
|
||
> 可以减少表结构变更对已有程序的影响
|
||
> 禁止使用子查询
|
||
> 虽然可使sql可读性好,但是缺点远远大于优点
|
||
> 子查询返回的结果集无法使用索引,结果集会被存储到一个临时表中,结果集越大性能越低
|
||
> 把子查询优化为join操作,但是并不是所有的都可以优化为join,一般情况下,只有当子查询是在in字句中,并且子查询是一个简单的sql(不包含union,group by,order by,limit)才能转换为关联查询
|
||
> 避免join过多的表
|
||
> 每join一个表会占一部分内存(join_buffer_size)
|
||
> 会产生临时表操作,影响查询效率
|
||
> mysql最多允许关联61个表,建议不超过5个
|
||
> 减少同数据库的交互次数
|
||
> 数据库更适合处理批量操作
|
||
> 合并多个相同的操作到一起,提高处理效率
|
||
> 使用in代替or
|
||
> in的值不要超过500个
|
||
> in 操作可以有效利用索引
|
||
> 禁止使用order by rand()进行随机排序
|
||
> 会把表中所有符合条件的数据装载到内存中进行排序
|
||
> 会消耗大量的cpu和io及内存资源
|
||
> 推荐在程序中获取随机值
|
||
> 禁止在where从句中对列进行函数转换和计算
|
||
> 导致无法使用相关列上的索引
|
||
> where date(create_time)=’20170901’ 写成 where create_time >= ‘20170901’ and create_time < ‘20170902’
|
||
> 在明显不会有重复值时使用union all而不是union
|
||
> union 会把所有数据放在临时表中后再进行去重操作,会多消耗内存,IO,网络资源
|
||
> union all 不会再对结果集进行去重操作
|
||
> 拆分复杂的大sql为多个小sql
|
||
> 目前mysql中一个sql只能使用一个cpu计算,不支持多cpu并行计算
|
||
> sql拆分后可以通过并行执行来提高处理效率
|
||
>
|
||
> ##### 六. 数据库操作行为规范
|
||
>
|
||
> 主要面向手动操作数据库的行为
|
||
> 超过100万的批量写操作,要分批多次进行操作
|
||
> 主从复制中:大批量操作可能会造成严重的主从延迟,因为当主库执行完成后,才会在从库执行
|
||
> binlog日志为row格式时会产生大量的日志
|
||
> 避免产生大量事务,产生阻塞,占满可用连接
|
||
> 对大表数据结构的修改一定要谨慎
|
||
> 可能会造成严重的锁表操作,尤其是生产环境,是不能忍受的
|
||
> 对于大表使用pt-online-schema-change修改表结构:
|
||
> 首先会建立一个与原表结构相同的新表
|
||
> 然后在新表上进行表结构的修改
|
||
> 然后把原表中的数据复制到新表中,并且增加一些触发器,以便把原表中即时新增的数据也复制到新表中
|
||
> 在行的所有数据复制完成之后,会在原表上增加一个很准的时间锁,同时把新表命名为原表,把原表删掉
|
||
> [实际上是把一个原子的DDL操作分解成多批次进行]
|
||
> [避免大表修改产生的主从延迟问题]
|
||
> [避免在对表字段进行修改时进行锁表]
|
||
> 禁止为程序使用的账号赋予super权限
|
||
> 当数据库连接数达到最大限制时,允许1个有super权限的用户连接
|
||
> super权限只能留给DBA处理问题的账号使用
|
||
> 对于程序连接数据库账号,遵循权限最小原则
|
||
> 程序使用的数据库账号只能在一个DB下使用,不准跨库
|
||
> 程序使用的账号原则上不准有drop权限
|
||
>
|
||
|
||
|
||
|
||
**docker安装mysql,远程访问**
|
||
|
||
```text
|
||
//搜索mysql
|
||
docker search mysql
|
||
//选定版本,抓取镜像
|
||
docker pull mysql:8.0
|
||
//创建同步mysql的文件夹
|
||
mkdir -p /data/mysql01
|
||
//创建容器
|
||
docker run --name mysql01 -p 3307:3306 -v /data/mysql01:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=zan123456 -d mysql:8.0
|
||
|
||
|
||
--restart 标志会检查容器的退出代码,并据此来决定是否要重启容器,默认是不会重启。
|
||
--restart的参数说明
|
||
always:无论容器的退出代码是什么,Docker都会自动重启该容器。
|
||
on-failure:只有当容器的退出代码为非0值的时候才会自动重启。另外,该参数还接受一个可选的重启次数参数,`--restart=on-fialure:5`表示当容器退出代码为非0时,Docker会尝试自动重启该容器,最多5次。
|
||
|
||
-v 容器内的 /var/lib/mysql 在宿主机上 /data/mysql01 做映射
|
||
-e MYSQL_ROOT_PASSWORD 初始密码
|
||
-p 将宿主机3306的端口映射到容器3306端口
|
||
```
|
||
|
||
**error:如果启动失败,查看日志docker logs mysql01提示**
|
||
|
||
chown: cannot read directory '/var/lib/mysql/': Permission denied
|
||
|
||
容器中没有执行权限 //挂载外部数据卷时,无法启动容器, 报 chown: cannot read directory '/var/lib/mysql/': Permission denied 由$ docker logs [name] 查看得知 该原因为centOs7默认开启selinux安全模块,需要临时关闭该安全模块,或者添加目录到白名单 临时关闭selinux:su -c "setenforce 0" 重新开启selinux:su -c "setenforce 1" 添加selinux规则,将要挂载的目录添加到白名单: 示例:chcon -Rt svirt_sandbox_file_t /data/mysql01(我启动挂载的路径)
|
||
|
||
|
||
|
||
**error:用navicat连接如果报错**
|
||
|
||
![img](https://pic2.zhimg.com/80/v2-8bc25b3599b809c5787eebee4d70067d_hd.jpg)报错是因为加密算法变了
|
||
|
||
我们在docker里面改变加密算法
|
||
|
||
```text
|
||
mysql> grant all PRIVILEGES on *.* to root@'%' WITH GRANT OPTION;
|
||
Query OK, 0 rows affected (0.01 sec)
|
||
|
||
mysql> ALTER user 'root'@'%' IDENTIFIED BY '123456' PASSWORD EXPIRE NEVER;
|
||
Query OK, 0 rows affected (0.11 sec)
|
||
|
||
mysql> ALTER user 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
|
||
Query OK, 0 rows affected (0.11 sec)
|
||
|
||
mysql> FLUSH PRIVILEGES;
|
||
Query OK, 0 rows affected (0.01 sec)
|
||
```
|
||
|
||
算法换成mysql_native_password即可
|
||
|
||
### 3-4 user数据表建立
|
||
|
||
配置application.yml
|
||
|
||
```
|
||
server:
|
||
port: 8080
|
||
spring:
|
||
datasource:
|
||
url: jdbc:mysql://192.168.253.133:3307/test?useUnicode=true&useSSL=false&characterEndcoding=utf8&useTimezone=true&serverTimezone=Asia/Shanghai
|
||
username: root
|
||
password: 123456
|
||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||
```
|
||
|
||
|
||
|
||
## 第四章 前端页面
|
||
|
||
|
||
|
||
### 4-1 前端登录login开发
|
||
|
||
前端使用uni-app
|
||
|
||
后端springboot2.X+mybatis plus
|
||
|
||
持久化数据库mysql8.0.16
|
||
|
||
效果展示:
|
||
|
||
![image](https://github.com/calvin008/weixin-login/blob/master/image/show.gif?raw=true)
|
||
|
||
#### 微信小程序登录步骤
|
||
|
||
![image](https://github.com/calvin008/weixin-login/blob/master/image/login-api.jpg?raw=true)
|
||
|
||
*第一步:小程序通过uni.login()获取code。*
|
||
|
||
*第二步:小程序通过uni.request()发送code到开发者服务器。*
|
||
|
||
*第三步:开发者服务器接收小程序发送的code,并携带appid、appsecret(这两个需要到微信小程序后台查看)、code发送到微信服务器。*
|
||
|
||
*第四步:微信服务器接收开发者服务器发送的appid、appsecret、code进行校验。校验通过后向开发者服务器发送session_key、openid。*
|
||
|
||
*第五步:开发者服务器自己生成一个key(自定义登录状态)与openid、session_key进行关联,并存到数据库中(mysql、redis等)。*
|
||
|
||
*第六步:开发者服务器返回生成key(自定义登录状态)到小程序。*
|
||
|
||
*第七步:小程序存储key(自定义登录状态)到本地。*
|
||
|
||
|
||
|
||
#### 首页index
|
||
|
||
```
|
||
<template>
|
||
<view class="content">
|
||
<image class="logo" :src="userInfo.avatarUrl || '/static/missing-face.png'"></image>
|
||
<view class="text-area">
|
||
<text class="title" @click="toLogin">{{ hasLogin ? userInfo.nickName || '未设置昵称' : '立即登录' }}</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { mapState } from 'vuex';
|
||
export default {
|
||
data() {
|
||
return {};
|
||
},
|
||
onLoad() {},
|
||
computed: {
|
||
...mapState(['hasLogin', 'userInfo'])
|
||
},
|
||
|
||
methods: {
|
||
toLogin() {
|
||
if (!this.hasLogin) {
|
||
uni.navigateTo({
|
||
url: '/pages/login/login'
|
||
});
|
||
}
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style>
|
||
.content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.logo {
|
||
height: 200rpx;
|
||
width: 200rpx;
|
||
margin-top: 200rpx;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
margin-bottom: 50rpx;
|
||
}
|
||
|
||
.text-area {
|
||
display: flex;
|
||
justify-content: center;
|
||
}
|
||
|
||
.title {
|
||
font-size: 36rpx;
|
||
color: #8f8f94;
|
||
}
|
||
</style>
|
||
|
||
```
|
||
|
||
|
||
|
||
#### 登录页面login
|
||
|
||
```
|
||
<template>
|
||
<view class="container">
|
||
<view class="left-top-sign">LOGIN</view>
|
||
<view class="welcome">欢迎回来!</view>
|
||
<button class="confirm-btn" open-type="getUserInfo" @getuserinfo="wxLogin" :disabled="logining">微信授权登录</button>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { mapMutations } from 'vuex';
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
logining: false
|
||
};
|
||
},
|
||
onLoad() {},
|
||
methods: {
|
||
wxLogin(e) {
|
||
const that = this;
|
||
that.logining = true;
|
||
let userInfo = e.detail.userInfo;
|
||
uni.login({
|
||
provider:"weixin",
|
||
success:(login_res => {
|
||
let code = login_res.code;
|
||
uni.getUserInfo({
|
||
success(info_res) {
|
||
console.log(info_res)
|
||
uni.request({
|
||
url:'http://localhost:8080/wxlogin',
|
||
method:"POST",
|
||
header: {
|
||
'content-type': 'application/x-www-form-urlencoded'
|
||
},
|
||
data:{
|
||
code : code,
|
||
rawData : info_res.rawData
|
||
},
|
||
success(res) {
|
||
if(res.data.status == 200){
|
||
that.$store.commit('login',userInfo);
|
||
// uni.setStorageSync("userInfo",userInfo);
|
||
// uni.setStorageSync("skey", res.data.data);
|
||
}else{
|
||
console.log('服务器异常')
|
||
}
|
||
},
|
||
fail(error) {
|
||
console.log(error)
|
||
}
|
||
})
|
||
uni.hideLoading()
|
||
uni.navigateBack()
|
||
}
|
||
})
|
||
|
||
})
|
||
})
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
.container {
|
||
display: flex;
|
||
overflow: hidden;
|
||
background: #fff;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
.left-top-sign {
|
||
font-size: 120upx;
|
||
color: $page-color-base;
|
||
position: relative;
|
||
left: -10upx;
|
||
margin-top: 100upx;
|
||
}
|
||
.welcome {
|
||
position: relative;
|
||
left: 50upx;
|
||
top: -90upx;
|
||
font-size: 46upx;
|
||
color: #555;
|
||
text-shadow: 1px 0px 1px rgba(0, 0, 0, 0.3);
|
||
}
|
||
.confirm-btn {
|
||
width: 630upx;
|
||
height: 76upx;
|
||
line-height: 76upx;
|
||
border-radius: 50px;
|
||
margin-top: 70upx;
|
||
background: $uni-color-primary;
|
||
color: #fff;
|
||
font-size: $font-lg;
|
||
&:after {
|
||
border-radius: 100px;
|
||
}
|
||
}
|
||
}
|
||
</style>
|
||
|
||
```
|
||
|
||
|
||
|
||
## 第五章 uni-app业务逻辑开发
|
||
|
||
### 5-1 vuex在uni-app中的使用
|
||
|
||
```
|
||
import Vue from 'vue'
|
||
import Vuex from 'vuex'
|
||
|
||
Vue.use(Vuex)
|
||
|
||
const store = new Vuex.Store({
|
||
state: {
|
||
hasLogin: false,
|
||
userInfo: {},
|
||
},
|
||
mutations: {
|
||
login(state, provider) {
|
||
|
||
state.hasLogin = true;
|
||
state.userInfo = provider;
|
||
uni.setStorage({//缓存用户登陆状态
|
||
key: 'userInfo',
|
||
data: provider
|
||
})
|
||
console.log(state.userInfo);
|
||
},
|
||
logout(state) {
|
||
state.hasLogin = false;
|
||
state.userInfo = {};
|
||
uni.removeStorage({
|
||
key: 'userInfo'
|
||
})
|
||
}
|
||
},
|
||
actions: {
|
||
|
||
}
|
||
|
||
})
|
||
|
||
export default store
|
||
```
|
||
|
||
|
||
|
||
### 5-2 登录功能实现
|
||
|
||
小程序已经抛弃getUserInfo,使用open-type绑定即可;
|
||
|
||
调用 wx.login 获取 code。
|
||
|
||
使用 wx.getSetting 获取用户的授权情况
|
||
|
||
- 如果用户已经授权,直接调用 API wx.getUserInfo 获取用户最新的信息;
|
||
- 用户未授权,在界面中显示一个按钮提示用户登入,当用户点击并授权后就获取到用户的最新信息。
|
||
|
||
将获取到的用户数据连同wx.login返回的code一同传给后端
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
## 第六章 springboot开发后端接口
|
||
|
||
### 6-1 entity
|
||
|
||
```
|
||
package top.weimumu.loginapi.entity;
|
||
|
||
import com.baomidou.mybatisplus.annotation.IdType;
|
||
import com.baomidou.mybatisplus.annotation.TableField;
|
||
import com.baomidou.mybatisplus.annotation.TableId;
|
||
import com.baomidou.mybatisplus.annotation.TableName;
|
||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||
import lombok.Data;
|
||
import org.springframework.format.annotation.DateTimeFormat;
|
||
|
||
import java.util.Date;
|
||
|
||
/**
|
||
* @author: create by calvin wong
|
||
* @date:2019/12/10
|
||
**/
|
||
|
||
@Data
|
||
@TableName("user")
|
||
public class User {
|
||
/**
|
||
* openid
|
||
*/
|
||
@TableId(value = "open_id",type = IdType.INPUT)
|
||
private String openId;
|
||
/**
|
||
* 用户头像
|
||
*/
|
||
private String avatarUrl;
|
||
/**
|
||
* 用户网名
|
||
*/
|
||
private String nickName;
|
||
/**
|
||
* session_key
|
||
*/
|
||
private String session_key;
|
||
/**
|
||
* skey
|
||
*/
|
||
private String skey;
|
||
/**
|
||
* 创建时间
|
||
*/
|
||
@TableField("create_time")
|
||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||
private Date createTime;
|
||
/**
|
||
* 最后登录时间
|
||
*/
|
||
@TableField("last_visit_time")
|
||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
|
||
private Date lastVisitTime;
|
||
|
||
}
|
||
|
||
```
|
||
|
||
### 6-2 mapper
|
||
|
||
```
|
||
package top.weimumu.loginapi.dao;
|
||
|
||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||
import top.weimumu.loginapi.entity.User;
|
||
|
||
/**
|
||
* @author: create by calvin wong
|
||
* @date:2019/12/4
|
||
**/
|
||
public interface UserMapper extends BaseMapper<User> {
|
||
|
||
}
|
||
|
||
```
|
||
|
||
### 6-3 common封装工具类
|
||
|
||
GolbalResult
|
||
|
||
```
|
||
package top.weimumu.loginapi.common;
|
||
|
||
/**
|
||
* @author: create by calvin wong
|
||
* @date:2019/12/10
|
||
**/
|
||
public class GlobalResult {
|
||
// 响应业务状态
|
||
private Integer status;
|
||
|
||
// 响应消息
|
||
private String msg;
|
||
|
||
// 响应中的数据
|
||
private Object data;
|
||
|
||
private String ok; // 不使用
|
||
|
||
public static GlobalResult build(Integer status, String msg, Object data) {
|
||
return new GlobalResult(status, msg, data);
|
||
}
|
||
|
||
public static GlobalResult ok(Object data) {
|
||
return new GlobalResult(data);
|
||
}
|
||
|
||
public static GlobalResult ok() {
|
||
return new GlobalResult(null);
|
||
}
|
||
|
||
public static GlobalResult errorMsg(String msg) {
|
||
return new GlobalResult(500, msg, null);
|
||
}
|
||
|
||
public static GlobalResult errorMap(Object data) {
|
||
return new GlobalResult(501, "error", data);
|
||
}
|
||
|
||
public static GlobalResult errorTokenMsg(String msg) {
|
||
return new GlobalResult(502, msg, null);
|
||
}
|
||
|
||
public static GlobalResult errorException(String msg) {
|
||
return new GlobalResult(555, msg, null);
|
||
}
|
||
|
||
public GlobalResult() {
|
||
|
||
}
|
||
|
||
public GlobalResult(Integer status, String msg, Object data) {
|
||
this.status = status;
|
||
this.msg = msg;
|
||
this.data = data;
|
||
}
|
||
|
||
public GlobalResult(Object data) {
|
||
this.status = 200;
|
||
this.msg = "OK";
|
||
this.data = data;
|
||
}
|
||
|
||
public Boolean isOK() {
|
||
return this.status == 200;
|
||
}
|
||
|
||
public Integer getStatus() {
|
||
return status;
|
||
}
|
||
|
||
public void setStatus(Integer status) {
|
||
this.status = status;
|
||
}
|
||
|
||
public String getMsg() {
|
||
return msg;
|
||
}
|
||
|
||
public void setMsg(String msg) {
|
||
this.msg = msg;
|
||
}
|
||
|
||
public Object getData() {
|
||
return data;
|
||
}
|
||
|
||
public void setData(Object data) {
|
||
this.data = data;
|
||
}
|
||
|
||
public String getOk() {
|
||
return ok;
|
||
}
|
||
|
||
public void setOk(String ok) {
|
||
this.ok = ok;
|
||
}
|
||
|
||
}
|
||
|
||
```
|
||
|
||
HttpClientUtils
|
||
|
||
```
|
||
package top.weimumu.loginapi.common;
|
||
|
||
import org.apache.http.NameValuePair;
|
||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||
import org.apache.http.client.methods.HttpGet;
|
||
import org.apache.http.client.methods.HttpPost;
|
||
import org.apache.http.client.utils.URIBuilder;
|
||
import org.apache.http.entity.ContentType;
|
||
import org.apache.http.entity.StringEntity;
|
||
import org.apache.http.impl.client.CloseableHttpClient;
|
||
import org.apache.http.impl.client.HttpClients;
|
||
import org.apache.http.message.BasicNameValuePair;
|
||
import org.apache.http.util.EntityUtils;
|
||
|
||
|
||
|
||
import java.io.IOException;
|
||
import java.net.URI;
|
||
import java.util.ArrayList;
|
||
import java.util.List;
|
||
import java.util.Map;
|
||
|
||
/**
|
||
* @author: create by calvin wong
|
||
* @date:2019/12/10
|
||
**/
|
||
public class HttpClientUtil {
|
||
public static String doGet(String url, Map<String, String> param) {
|
||
|
||
// 创建Httpclient对象
|
||
CloseableHttpClient httpclient = HttpClients.createDefault();
|
||
|
||
String resultString = "";
|
||
CloseableHttpResponse response = null;
|
||
try {
|
||
// 创建uri
|
||
URIBuilder builder = new URIBuilder(url);
|
||
if (param != null) {
|
||
for (String key : param.keySet()) {
|
||
builder.addParameter(key, param.get(key));
|
||
}
|
||
}
|
||
URI uri = builder.build();
|
||
|
||
// 创建http GET请求
|
||
HttpGet httpGet = new HttpGet(uri);
|
||
|
||
// 执行请求
|
||
response = httpclient.execute(httpGet);
|
||
// 判断返回状态是否为200
|
||
if (response.getStatusLine().getStatusCode() == 200) {
|
||
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
|
||
}
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
} finally {
|
||
try {
|
||
if (response != null) {
|
||
response.close();
|
||
}
|
||
httpclient.close();
|
||
} catch (IOException e) {
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
return resultString;
|
||
}
|
||
|
||
public static String doGet(String url) {
|
||
return doGet(url, null);
|
||
}
|
||
|
||
public static String doPost(String url, Map<String, String> param) {
|
||
// 创建Httpclient对象
|
||
CloseableHttpClient httpClient = HttpClients.createDefault();
|
||
CloseableHttpResponse response = null;
|
||
String resultString = "";
|
||
try {
|
||
// 创建Http Post请求
|
||
HttpPost httpPost = new HttpPost(url);
|
||
// 创建参数列表
|
||
if (param != null) {
|
||
List<NameValuePair> paramList = new ArrayList<>();
|
||
for (String key : param.keySet()) {
|
||
paramList.add(new BasicNameValuePair(key, param.get(key)));
|
||
}
|
||
// 模拟表单
|
||
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
|
||
httpPost.setEntity(entity);
|
||
}
|
||
// 执行http请求
|
||
response = httpClient.execute(httpPost);
|
||
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
} finally {
|
||
try {
|
||
response.close();
|
||
} catch (IOException e) {
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
|
||
return resultString;
|
||
}
|
||
|
||
public static String doPost(String url) {
|
||
return doPost(url, null);
|
||
}
|
||
|
||
public static String doPostJson(String url, String json) {
|
||
// 创建Httpclient对象
|
||
CloseableHttpClient httpClient = HttpClients.createDefault();
|
||
CloseableHttpResponse response = null;
|
||
String resultString = "";
|
||
try {
|
||
// 创建Http Post请求
|
||
HttpPost httpPost = new HttpPost(url);
|
||
// 创建请求内容
|
||
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
|
||
httpPost.setEntity(entity);
|
||
// 执行http请求
|
||
response = httpClient.execute(httpPost);
|
||
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
|
||
} catch (Exception e) {
|
||
e.printStackTrace();
|
||
} finally {
|
||
try {
|
||
response.close();
|
||
} catch (IOException e) {
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
|
||
return resultString;
|
||
}
|
||
|
||
}
|
||
|
||
```
|
||
|
||
WechatUtil
|
||
|
||
```
|
||
package top.weimumu.loginapi.common;
|
||
|
||
import com.alibaba.fastjson.JSON;
|
||
import com.alibaba.fastjson.JSONObject;
|
||
import org.apache.shiro.codec.Base64;
|
||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||
|
||
|
||
import javax.crypto.Cipher;
|
||
import javax.crypto.spec.IvParameterSpec;
|
||
import javax.crypto.spec.SecretKeySpec;
|
||
import java.security.AlgorithmParameters;
|
||
import java.security.Security;
|
||
import java.util.Arrays;
|
||
import java.util.HashMap;
|
||
import java.util.Map;
|
||
|
||
/**
|
||
* @author: create by calvin wong
|
||
* @date:2019/12/10
|
||
**/
|
||
public class WechatUtil {
|
||
public static JSONObject getSessionKeyOrOpenId(String code) {
|
||
String requestUrl = "https://api.weixin.qq.com/sns/jscode2session";
|
||
Map<String, String> requestUrlParam = new HashMap<>();
|
||
// https://mp.weixin.qq.com/wxopen/devprofile?action=get_profile&token=164113089&lang=zh_CN
|
||
//小程序appId
|
||
requestUrlParam.put("appid", "wx62e0151eaf62eff7");
|
||
//小程序secret
|
||
requestUrlParam.put("secret", "c45170b3aa8dbc5cd45ab12c319298f8");
|
||
//小程序端返回的code
|
||
requestUrlParam.put("js_code", code);
|
||
//默认参数
|
||
requestUrlParam.put("grant_type", "authorization_code");
|
||
//发送post请求读取调用微信接口获取openid用户唯一标识
|
||
JSONObject jsonObject = JSON.parseObject(HttpClientUtil.doPost(requestUrl, requestUrlParam));
|
||
return jsonObject;
|
||
}
|
||
|
||
public static JSONObject getUserInfo(String encryptedData, String sessionKey, String iv) {
|
||
// 被加密的数据
|
||
byte[] dataByte = Base64.decode(encryptedData);
|
||
// 加密秘钥
|
||
byte[] keyByte = Base64.decode(sessionKey);
|
||
// 偏移量
|
||
byte[] ivByte = Base64.decode(iv);
|
||
try {
|
||
// 如果密钥不足16位,那么就补足. 这个if 中的内容很重要
|
||
int base = 16;
|
||
if (keyByte.length % base != 0) {
|
||
int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
|
||
byte[] temp = new byte[groups * base];
|
||
Arrays.fill(temp, (byte) 0);
|
||
System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
|
||
keyByte = temp;
|
||
}
|
||
// 初始化
|
||
Security.addProvider(new BouncyCastleProvider());
|
||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
|
||
SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
|
||
AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
|
||
parameters.init(new IvParameterSpec(ivByte));
|
||
cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化
|
||
byte[] resultByte = cipher.doFinal(dataByte);
|
||
if (null != resultByte && resultByte.length > 0) {
|
||
String result = new String(resultByte, "UTF-8");
|
||
return JSON.parseObject(result);
|
||
}
|
||
} catch (Exception e) {
|
||
}
|
||
return null;
|
||
}
|
||
|
||
}
|
||
|
||
```
|
||
|
||
### 6-4 controller
|
||
|
||
```
|
||
package top.weimumu.loginapi.controller;
|
||
|
||
|
||
import com.alibaba.fastjson.JSON;
|
||
import com.alibaba.fastjson.JSONObject;
|
||
import org.springframework.beans.factory.annotation.Autowired;
|
||
import org.springframework.web.bind.annotation.PostMapping;
|
||
import org.springframework.web.bind.annotation.RequestParam;
|
||
import org.springframework.web.bind.annotation.RestController;
|
||
import top.weimumu.loginapi.common.GlobalResult;
|
||
import top.weimumu.loginapi.common.WechatUtil;
|
||
import top.weimumu.loginapi.dao.UserMapper;
|
||
import top.weimumu.loginapi.entity.User;
|
||
|
||
import java.util.Date;
|
||
import java.util.UUID;
|
||
|
||
/**
|
||
* @author: create by calvin wong
|
||
* @date:2019/12/4
|
||
**/
|
||
@RestController
|
||
public class UserController {
|
||
|
||
@Autowired
|
||
private UserMapper userMapper;
|
||
|
||
@PostMapping("/wxlogin")
|
||
public GlobalResult wxLogin(
|
||
@RequestParam(value = "code", required = false) String code,
|
||
@RequestParam(value = "rawData", required = false) String rawData
|
||
) {
|
||
JSONObject rawDataJson = JSON.parseObject(rawData);
|
||
JSONObject SessionKeyOpenId = WechatUtil.getSessionKeyOrOpenId(code);
|
||
String openid = SessionKeyOpenId.getString("openid");
|
||
String sessionKey = SessionKeyOpenId.getString("session_key");
|
||
User user = this.userMapper.selectById(openid);
|
||
String skey = UUID.randomUUID().toString();
|
||
if (user == null) {
|
||
String nickName = rawDataJson.getString("nickName");
|
||
String avatarUrl = rawDataJson.getString("avatarUrl");
|
||
user = new User();
|
||
user.setOpenId(openid);
|
||
user.setSkey(skey);
|
||
user.setCreateTime(new Date());
|
||
user.setLastVisitTime(new Date());
|
||
user.setSession_key(sessionKey);
|
||
user.setAvatarUrl(avatarUrl);
|
||
user.setNickName(nickName);
|
||
this.userMapper.insert(user);
|
||
}else {
|
||
// 已存在,更新用户登录时间
|
||
|
||
user.setLastVisitTime(new Date());
|
||
// // 重新设置会话skey
|
||
user.setSkey(skey);
|
||
|
||
this.userMapper.updateById(user);
|
||
}
|
||
GlobalResult result = GlobalResult.build(200, null, skey);
|
||
return result;
|
||
}
|
||
}
|
||
|
||
```
|
||
|