初始化
authorliangzhenying <867174124@qq.com>
Thu, 31 Jul 2025 07:30:07 +0000 (15:30 +0800)
committerliangzhenying <867174124@qq.com>
Thu, 31 Jul 2025 07:30:07 +0000 (15:30 +0800)
355 files changed:
.gitignore
LingQi/LingQi.xcodeproj/project.pbxproj [new file with mode: 0644]
LingQi/LingQi.xcodeproj/project.xcworkspace/contents.xcworkspacedata [new file with mode: 0644]
LingQi/LingQi.xcworkspace/contents.xcworkspacedata [new file with mode: 0644]
LingQi/LingQi/Api/HttpClient.swift [new file with mode: 0644]
LingQi/LingQi/Api/ResponseBaseModel.swift [new file with mode: 0644]
LingQi/LingQi/AppDelegate.swift [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/AccentColor.colorset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/AppIcon.appiconset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/bg_base.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/bg_base.imageset/bg_base.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/bg_login.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/bg_login.imageset/bg_login.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/bg_mine_order.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/bg_mine_order.imageset/bg_mine_order.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/bg_mine_order2.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/bg_mine_order2.imageset/bg_mine_order2.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/bg_splash.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/bg_splash.imageset/bg_splash.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/dialog_bg.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/dialog_bg.imageset/dialog_bg.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/dialog_bg_2.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/dialog_bg_2.imageset/dialog_bg_2.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_ai_config.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_ai_config.imageset/ic_ai_config.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_break.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_break.imageset/ic_break.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_check.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_check.imageset/ic_check.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_connect_link.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_connect_link.imageset/ic_connect_link.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_connect_log.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_connect_log.imageset/ic_connect_log.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_connect_log1.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_connect_log1.imageset/ic_connect_log1.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_connect_product.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_connect_product.imageset/ic_connect_product.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_connect_product1.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_connect_product1.imageset/ic_connect_product1.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_device_set.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_device_set.imageset/ic_device_set.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_dui.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_dui.imageset/ic_dui.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_edit.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_edit.imageset/ic_edit.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_false.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_false.imageset/ic_false.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_finger.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_finger.imageset/ic_finger.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_add.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_add.imageset/ic_home_add.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_home.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_home.imageset/ic_home_home.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_home_sel.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_home_sel.imageset/ic_home_home_sel.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_mine.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_mine.imageset/ic_home_mine.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_mine_sel.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_mine_sel.imageset/ic_home_mine_sel.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_nodevice.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_nodevice.imageset/ic_home_nodevice.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_scan.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_scan.imageset/ic_home_scan.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_tv.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_home_tv.imageset/ic_home_tv.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_link.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_link.imageset/ic_link.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_linked.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_linked.imageset/ic_linked.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_logo.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_logo.imageset/ic_logo.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_mac.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_mac.imageset/ic_mac.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_man.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_man.imageset/ic_man.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_mine_1.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_mine_1.imageset/ic_mine_1.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_mine_2.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_mine_2.imageset/ic_mine_2.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_mine_3.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_mine_3.imageset/ic_mine_3.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_more.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_more.imageset/ic_more.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_more2.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_more2.imageset/ic_more2.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_msg_recoder.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_msg_recoder.imageset/ic_msg_recoder.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_nopub.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_nopub.imageset/ic_nopub.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_power.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_power.imageset/ic_power.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_product.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_product.imageset/ic_product.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_remainber.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_remainber.imageset/ic_remainber.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_role.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_role.imageset/ic_role.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_scam.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_scam.imageset/ic_scam.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_seach.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_seach.imageset/ic_seach.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_speak.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_speak.imageset/ic_speak.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_speek.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_speek.imageset/ic_speek.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_sure.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_sure.imageset/ic_sure.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_tip.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_tip.imageset/ic_tip.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_unlink.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_unlink.imageset/ic_unlink.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_user.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_user.imageset/ic_user.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_vip_year.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_vip_year.imageset/ic_vip_year.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_voice.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_voice.imageset/ic_voice.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_voice_jia.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_voice_jia.imageset/ic_voice_jia.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_voice_jian.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_voice_jian.imageset/ic_voice_jian.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_wifi1.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_wifi1.imageset/ic_wifi1.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_wifi2.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_wifi2.imageset/ic_wifi2.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_wifi3.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_wifi3.imageset/ic_wifi3.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_wifi4.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_wifi4.imageset/ic_wifi4.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_woman.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_woman.imageset/ic_woman.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_yinse.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/ic_yinse.imageset/ic_yinse.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/loading.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/loading.imageset/loading.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/splash_tv.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/an/splash_tv.imageset/splash_tv.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/081_发现.imageset/081_发现.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/081_发现.imageset/081_发现@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/081_发现.imageset/081_发现@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/081_发现.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Frame 134.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Frame 134.imageset/Frame 134.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Frame 134.imageset/Frame 134@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Frame 134.imageset/Frame 134@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Frame 220.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Frame 220.imageset/Frame 220.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Frame 220.imageset/Frame 220@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Frame 220.imageset/Frame 220@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Group 347.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Group 347.imageset/Group 347.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Group 347.imageset/Group 347@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Group 347.imageset/Group 347@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Group 352.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Group 352.imageset/Group 352.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Group 352.imageset/Group 352@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/Group 352.imageset/Group 352@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_0_normal.imageset/081_主页.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_0_normal.imageset/081_主页@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_0_normal.imageset/081_主页@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_0_normal.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_0_selected.imageset/081_主页.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_0_selected.imageset/081_主页@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_0_selected.imageset/081_主页@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_0_selected.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_1_normal.imageset/081_我的.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_1_normal.imageset/081_我的@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_1_normal.imageset/081_我的@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_1_normal.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_1_selected.imageset/081_我的.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_1_selected.imageset/081_我的@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_1_selected.imageset/081_我的@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/tab_1_selected.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/空内容.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/空内容.imageset/空内容.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/空内容.imageset/空内容@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/home/空内容.imageset/空内容@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Frame 1453.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Frame 1453.imageset/Frame 1453.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Frame 1453.imageset/Frame 1453@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Frame 1453.imageset/Frame 1453@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Frame(1).imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Frame(1).imageset/Frame(1).png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Frame(1).imageset/Frame@2x(1).png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Frame(1).imageset/Frame@3x(1).png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Frame(2).imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Frame(2).imageset/Frame(2).png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Frame(2).imageset/Frame@2x(2).png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Frame(2).imageset/Frame@3x(2).png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Rectangle 268.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Rectangle 268.imageset/Rectangle 268.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Rectangle 268.imageset/Rectangle 268@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Rectangle 268.imageset/Rectangle 268@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Rectangle 273.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Rectangle 273.imageset/Rectangle 273.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Rectangle 273.imageset/Rectangle 273@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/Rectangle 273.imageset/Rectangle 273@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/arrow_back.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/arrow_back.imageset/ic_back.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/arrow_next.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/arrow_next.imageset/个人中心-进入 1.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/arrow_next.imageset/个人中心-进入 1@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/arrow_next.imageset/个人中心-进入 1@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/image 57.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/image 57.imageset/image 57.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/image 57.imageset/image 57@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/image 57.imageset/image 57@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/login_cover.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/login_cover.imageset/Frame 134.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/login_cover.imageset/Frame 134@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/login_cover.imageset/Frame 134@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/login_logo.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/login_logo.imageset/Group 281.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/login_logo.imageset/Group 281@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/login_logo.imageset/Group 281@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_cell_device.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_cell_device.imageset/Frame.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_cell_device.imageset/Frame@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_cell_device.imageset/Frame@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_cell_product.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_cell_product.imageset/信息.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_cell_product.imageset/信息@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_cell_product.imageset/信息@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_cell_service.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_cell_service.imageset/转账.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_cell_service.imageset/转账@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_cell_service.imageset/转账@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_msg.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_msg.imageset/ic_msg.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_set.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/mine_set.imageset/ic_set.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/select_normal.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/select_normal.imageset/Frame.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/select_normal.imageset/Frame@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/select_normal.imageset/Frame@3x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/select_selected.imageset/Contents.json [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/select_selected.imageset/Group 334.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/select_selected.imageset/Group 334@2x.png [new file with mode: 0644]
LingQi/LingQi/Assets.xcassets/mine/select_selected.imageset/Group 334@3x.png [new file with mode: 0644]
LingQi/LingQi/Base.lproj/LaunchScreen.storyboard [new file with mode: 0644]
LingQi/LingQi/Base.lproj/Main.storyboard [new file with mode: 0644]
LingQi/LingQi/Ble/BlueToothManager.swift [new file with mode: 0644]
LingQi/LingQi/Ble/BlueToothViewModel.swift [new file with mode: 0644]
LingQi/LingQi/Ble/ReceiveManager.swift [new file with mode: 0644]
LingQi/LingQi/Ble/ScanModel.swift [new file with mode: 0644]
LingQi/LingQi/Ble/SendManager.swift [new file with mode: 0644]
LingQi/LingQi/Info.plist [new file with mode: 0644]
LingQi/LingQi/LingQi-Bridging-Header.h [new file with mode: 0644]
LingQi/LingQi/MixApi/MixApi.swift [new file with mode: 0644]
LingQi/LingQi/Resource/colors/Colors+YL.swift [new file with mode: 0644]
LingQi/LingQi/Resource/colors/Colors.swift [new file with mode: 0644]
LingQi/LingQi/Resource/fonts/UIFont+ZKYS.swift [new file with mode: 0644]
LingQi/LingQi/SceneDelegate.swift [new file with mode: 0644]
LingQi/LingQi/Tools/BaseSizeMacro.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Category/Data+YL.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Category/Open+map.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/Array+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/Array+Spec.swift [new file with mode: 0755]
LingQi/LingQi/Tools/Extensions/CAGradientLayer+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/CALayer+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/CGRect+HTDevelop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/CGSize+Fit.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/Codable+Spec.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/CollectionExtensions.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/ConstraintArrayDSL.swift [new file with mode: 0755]
LingQi/LingQi/Tools/Extensions/Dictionary+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/DispatchQueue+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/FileManager+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/KeyPath+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/Number+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/QueryParameters.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/Sequence+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/SignedNumericExtensions.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/SnapKit_Extension.swift [new file with mode: 0755]
LingQi/LingQi/Tools/Extensions/String+Attribute.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/String+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/String+Encryption.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/String+RegExp.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/String+SubString.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/String+Week.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/String+YL.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/StringURL+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/Time+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/UIApplication+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/UIButton+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/UIDevice+Landscape.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/UIImage+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/UIImage+Gif.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/UIImage+ImageEffects.h [new file with mode: 0755]
LingQi/LingQi/Tools/Extensions/UIImage+ImageEffects.m [new file with mode: 0755]
LingQi/LingQi/Tools/Extensions/UIImageView+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/UINavigationBar+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/UITableView+Header.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/UITableView_Extension.swift [new file with mode: 0755]
LingQi/LingQi/Tools/Extensions/UITextField+Extension.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/UIView+Develop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/UIView+Loading.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/UIView+Rect.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/UIView+Round.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/UIViewExtension.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/YCDevelop.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Extensions/zhString.swift [new file with mode: 0644]
LingQi/LingQi/Tools/LogManager.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Logs.swift [new file with mode: 0644]
LingQi/LingQi/Tools/NumberToTime.swift [new file with mode: 0644]
LingQi/LingQi/Tools/ShareView.swift [new file with mode: 0644]
LingQi/LingQi/Tools/SizeFit.swift [new file with mode: 0644]
LingQi/LingQi/Tools/Then.swift [new file with mode: 0755]
LingQi/LingQi/Tools/TimerButton/YLTimerButton.h [new file with mode: 0644]
LingQi/LingQi/Tools/TimerButton/YLTimerButton.m [new file with mode: 0644]
LingQi/LingQi/UI/Base/BaseNC.swift [new file with mode: 0644]
LingQi/LingQi/UI/Base/BaseNavigation.swift [new file with mode: 0644]
LingQi/LingQi/UI/Base/BasePickerView.swift [new file with mode: 0644]
LingQi/LingQi/UI/Base/BasePresentView.swift [new file with mode: 0644]
LingQi/LingQi/UI/Base/BaseTC.swift [new file with mode: 0644]
LingQi/LingQi/UI/Base/BaseTableViewCell.swift [new file with mode: 0644]
LingQi/LingQi/UI/Base/BaseTableViewSetionHeader.swift [new file with mode: 0644]
LingQi/LingQi/UI/Base/BaseTextField.swift [new file with mode: 0644]
LingQi/LingQi/UI/Base/BaseVC.swift [new file with mode: 0644]
LingQi/LingQi/UI/Base/BaseVM.swift [new file with mode: 0644]
LingQi/LingQi/UI/Base/BaseView.swift [new file with mode: 0644]
LingQi/LingQi/UI/Base/ReusabelViewsInitProtocol.swift [new file with mode: 0644]
LingQi/LingQi/UI/Base/WebView/BaseWebView.swift [new file with mode: 0644]
LingQi/LingQi/UI/Base/WebView/BaseWebViewController.swift [new file with mode: 0644]
LingQi/LingQi/UI/Base/YLprogressHUD.swift [new file with mode: 0644]
LingQi/LingQi/UI/Device/DeviceVC.swift [new file with mode: 0644]
LingQi/LingQi/UI/Discover/DiscoverVC.swift [new file with mode: 0644]
LingQi/LingQi/UI/Home/HomeVC.swift [new file with mode: 0644]
LingQi/LingQi/UI/Mine/Login/AgreeView.swift [new file with mode: 0644]
LingQi/LingQi/UI/Mine/Login/CodeView.swift [new file with mode: 0644]
LingQi/LingQi/UI/Mine/Login/LoginVC.swift [new file with mode: 0644]
LingQi/LingQi/UI/Mine/Login/LoginVM.swift [new file with mode: 0644]
LingQi/LingQi/UI/Mine/Login/PhoneView.swift [new file with mode: 0644]
LingQi/LingQi/UI/Mine/Login/UserModel.swift [new file with mode: 0644]
LingQi/LingQi/UI/Mine/Root/MineCell.swift [new file with mode: 0644]
LingQi/LingQi/UI/Mine/Root/MineHeaderView.swift [new file with mode: 0644]
LingQi/LingQi/UI/Mine/Root/MineNavBar.swift [new file with mode: 0644]
LingQi/LingQi/UI/Mine/Root/MineOrderView.swift [new file with mode: 0644]
LingQi/LingQi/UI/Mine/Root/MineUserInfoView.swift [new file with mode: 0644]
LingQi/LingQi/UI/Mine/Root/MineVC.swift [new file with mode: 0644]
LingQi/LingQi/UI/Mine/UserInfo/UserInfoCell.swift [new file with mode: 0644]
LingQi/LingQi/UI/Mine/UserInfo/UserInfoSectionHeader.swift [new file with mode: 0644]
LingQi/LingQi/UI/Mine/UserInfo/UserInfoVC.swift [new file with mode: 0644]
LingQi/LingQi/UI/Scan/DeviceCell.swift [new file with mode: 0644]
LingQi/LingQi/UI/Scan/ScanDeviceVC.swift [new file with mode: 0644]
LingQi/LingQi/UI/common/AgreeMentPopView.swift [new file with mode: 0644]
LingQi/LingQi/UI/common/CustomButton.swift [new file with mode: 0644]
LingQi/LingQi/UI/common/ImagePickerManager.swift [new file with mode: 0644]
LingQi/LingQi/ViewController.swift [new file with mode: 0644]
LingQi/Podfile.lock [new file with mode: 0644]
LingQi/podfile [new file with mode: 0644]

index 330d167..79ef012 100644 (file)
@@ -46,7 +46,7 @@ playground.xcworkspace
 # hence it is not needed unless you have added a package configuration file to your project
 # .swiftpm
 
-.build/
+LingQi/build/
 
 # CocoaPods
 #
@@ -54,7 +54,7 @@ playground.xcworkspace
 # you should judge for yourself, the pros and cons are mentioned at:
 # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
 #
-# Pods/
+ .LingQi/Pods/
 #
 # Add this line if you want to avoid checking in source code from the Xcode workspace
 # *.xcworkspace
@@ -88,3 +88,4 @@ fastlane/test_output
 # https://github.com/johnno1962/injectionforxcode
 
 iOSInjectionProject/
+LingQi/Pods
diff --git a/LingQi/LingQi.xcodeproj/project.pbxproj b/LingQi/LingQi.xcodeproj/project.pbxproj
new file mode 100644 (file)
index 0000000..bd9ef20
--- /dev/null
@@ -0,0 +1,425 @@
+// !$*UTF8*$!
+{
+       archiveVersion = 1;
+       classes = {
+       };
+       objectVersion = 77;
+       objects = {
+
+/* Begin PBXBuildFile section */
+               028546BADEA3BE9A60C07D60 /* Pods_LingQi.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 68EBF8E8F60D33549C862B1B /* Pods_LingQi.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+               3F887B9C2E38D8DC00C98658 /* LingQi.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LingQi.app; sourceTree = BUILT_PRODUCTS_DIR; };
+               68EBF8E8F60D33549C862B1B /* Pods_LingQi.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LingQi.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+               CB933A7969ADF81D59503790 /* Pods-LingQi.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LingQi.debug.xcconfig"; path = "Target Support Files/Pods-LingQi/Pods-LingQi.debug.xcconfig"; sourceTree = "<group>"; };
+               CE98543C79FAAB6CEF4CBFCA /* Pods-LingQi.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LingQi.release.xcconfig"; path = "Target Support Files/Pods-LingQi/Pods-LingQi.release.xcconfig"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
+               3F887BAE2E38D8DD00C98658 /* Exceptions for "LingQi" folder in "LingQi" target */ = {
+                       isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
+                       membershipExceptions = (
+                               Info.plist,
+                       );
+                       target = 3F887B9B2E38D8DC00C98658 /* LingQi */;
+               };
+/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
+
+/* Begin PBXFileSystemSynchronizedRootGroup section */
+               3F887B9E2E38D8DC00C98658 /* LingQi */ = {
+                       isa = PBXFileSystemSynchronizedRootGroup;
+                       exceptions = (
+                               3F887BAE2E38D8DD00C98658 /* Exceptions for "LingQi" folder in "LingQi" target */,
+                       );
+                       path = LingQi;
+                       sourceTree = "<group>";
+               };
+/* End PBXFileSystemSynchronizedRootGroup section */
+
+/* Begin PBXFrameworksBuildPhase section */
+               3F887B992E38D8DC00C98658 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               028546BADEA3BE9A60C07D60 /* Pods_LingQi.framework in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+               34A14A83ECF09370871C891F /* Pods */ = {
+                       isa = PBXGroup;
+                       children = (
+                               CB933A7969ADF81D59503790 /* Pods-LingQi.debug.xcconfig */,
+                               CE98543C79FAAB6CEF4CBFCA /* Pods-LingQi.release.xcconfig */,
+                       );
+                       path = Pods;
+                       sourceTree = "<group>";
+               };
+               3F887B932E38D8DC00C98658 = {
+                       isa = PBXGroup;
+                       children = (
+                               3F887B9E2E38D8DC00C98658 /* LingQi */,
+                               3F887B9D2E38D8DC00C98658 /* Products */,
+                               34A14A83ECF09370871C891F /* Pods */,
+                               676B86A4BA2639E8694D56B4 /* Frameworks */,
+                       );
+                       sourceTree = "<group>";
+               };
+               3F887B9D2E38D8DC00C98658 /* Products */ = {
+                       isa = PBXGroup;
+                       children = (
+                               3F887B9C2E38D8DC00C98658 /* LingQi.app */,
+                       );
+                       name = Products;
+                       sourceTree = "<group>";
+               };
+               676B86A4BA2639E8694D56B4 /* Frameworks */ = {
+                       isa = PBXGroup;
+                       children = (
+                               68EBF8E8F60D33549C862B1B /* Pods_LingQi.framework */,
+                       );
+                       name = Frameworks;
+                       sourceTree = "<group>";
+               };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+               3F887B9B2E38D8DC00C98658 /* LingQi */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = 3F887BAF2E38D8DD00C98658 /* Build configuration list for PBXNativeTarget "LingQi" */;
+                       buildPhases = (
+                               FEE3A20D8A2FA81E622C488B /* [CP] Check Pods Manifest.lock */,
+                               3F887B982E38D8DC00C98658 /* Sources */,
+                               3F887B992E38D8DC00C98658 /* Frameworks */,
+                               3F887B9A2E38D8DC00C98658 /* Resources */,
+                               5A934A35F54A5620CFD3C08A /* [CP] Embed Pods Frameworks */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       fileSystemSynchronizedGroups = (
+                               3F887B9E2E38D8DC00C98658 /* LingQi */,
+                       );
+                       name = LingQi;
+                       productName = LingQi;
+                       productReference = 3F887B9C2E38D8DC00C98658 /* LingQi.app */;
+                       productType = "com.apple.product-type.application";
+               };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+               3F887B942E38D8DC00C98658 /* Project object */ = {
+                       isa = PBXProject;
+                       attributes = {
+                               BuildIndependentTargetsInParallel = 1;
+                               LastSwiftUpdateCheck = 1640;
+                               LastUpgradeCheck = 1640;
+                               TargetAttributes = {
+                                       3F887B9B2E38D8DC00C98658 = {
+                                               CreatedOnToolsVersion = 16.4;
+                                       };
+                               };
+                       };
+                       buildConfigurationList = 3F887B972E38D8DC00C98658 /* Build configuration list for PBXProject "LingQi" */;
+                       developmentRegion = en;
+                       hasScannedForEncodings = 0;
+                       knownRegions = (
+                               en,
+                               Base,
+                       );
+                       mainGroup = 3F887B932E38D8DC00C98658;
+                       minimizedProjectReferenceProxies = 1;
+                       preferredProjectObjectVersion = 77;
+                       productRefGroup = 3F887B9D2E38D8DC00C98658 /* Products */;
+                       projectDirPath = "";
+                       projectRoot = "";
+                       targets = (
+                               3F887B9B2E38D8DC00C98658 /* LingQi */,
+                       );
+               };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+               3F887B9A2E38D8DC00C98658 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+               5A934A35F54A5620CFD3C08A /* [CP] Embed Pods Frameworks */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputFileListPaths = (
+                               "${PODS_ROOT}/Target Support Files/Pods-LingQi/Pods-LingQi-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+                       );
+                       inputPaths = (
+                       );
+                       name = "[CP] Embed Pods Frameworks";
+                       outputFileListPaths = (
+                               "${PODS_ROOT}/Target Support Files/Pods-LingQi/Pods-LingQi-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+                       );
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-LingQi/Pods-LingQi-frameworks.sh\"\n";
+                       showEnvVarsInLog = 0;
+               };
+               FEE3A20D8A2FA81E622C488B /* [CP] Check Pods Manifest.lock */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputFileListPaths = (
+                       );
+                       inputPaths = (
+                               "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+                               "${PODS_ROOT}/Manifest.lock",
+                       );
+                       name = "[CP] Check Pods Manifest.lock";
+                       outputFileListPaths = (
+                       );
+                       outputPaths = (
+                               "$(DERIVED_FILE_DIR)/Pods-LingQi-checkManifestLockResult.txt",
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+                       showEnvVarsInLog = 0;
+               };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+               3F887B982E38D8DC00C98658 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+               3F887BB02E38D8DD00C98658 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = CB933A7969ADF81D59503790 /* Pods-LingQi.debug.xcconfig */;
+                       buildSettings = {
+                               ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+                               ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+                               CODE_SIGN_STYLE = Automatic;
+                               CURRENT_PROJECT_VERSION = 1;
+                               DEVELOPMENT_TEAM = M33X987285;
+                               GENERATE_INFOPLIST_FILE = YES;
+                               INFOPLIST_FILE = LingQi/Info.plist;
+                               INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
+                               INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
+                               INFOPLIST_KEY_UIMainStoryboardFile = Main;
+                               INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+                               INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+                               IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+                               LD_RUNPATH_SEARCH_PATHS = (
+                                       "$(inherited)",
+                                       "@executable_path/Frameworks",
+                               );
+                               MARKETING_VERSION = 1.0;
+                               PRODUCT_BUNDLE_IDENTIFIER = demo.LingQi;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
+                               SUPPORTS_MACCATALYST = NO;
+                               SWIFT_EMIT_LOC_STRINGS = YES;
+                               SWIFT_OBJC_BRIDGING_HEADER = "LingQi/LingQi-Bridging-Header.h";
+                               SWIFT_VERSION = 5.0;
+                               TARGETED_DEVICE_FAMILY = 1;
+                       };
+                       name = Debug;
+               };
+               3F887BB12E38D8DD00C98658 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = CE98543C79FAAB6CEF4CBFCA /* Pods-LingQi.release.xcconfig */;
+                       buildSettings = {
+                               ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+                               ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+                               CODE_SIGN_STYLE = Automatic;
+                               CURRENT_PROJECT_VERSION = 1;
+                               DEVELOPMENT_TEAM = M33X987285;
+                               GENERATE_INFOPLIST_FILE = YES;
+                               INFOPLIST_FILE = LingQi/Info.plist;
+                               INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
+                               INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
+                               INFOPLIST_KEY_UIMainStoryboardFile = Main;
+                               INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+                               INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+                               IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+                               LD_RUNPATH_SEARCH_PATHS = (
+                                       "$(inherited)",
+                                       "@executable_path/Frameworks",
+                               );
+                               MARKETING_VERSION = 1.0;
+                               PRODUCT_BUNDLE_IDENTIFIER = demo.LingQi;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
+                               SUPPORTS_MACCATALYST = NO;
+                               SWIFT_EMIT_LOC_STRINGS = YES;
+                               SWIFT_OBJC_BRIDGING_HEADER = "LingQi/LingQi-Bridging-Header.h";
+                               SWIFT_VERSION = 5.0;
+                               TARGETED_DEVICE_FAMILY = 1;
+                       };
+                       name = Release;
+               };
+               3F887BB22E38D8DD00C98658 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+                               CLANG_ANALYZER_NONNULL = YES;
+                               CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+                               CLANG_ENABLE_MODULES = YES;
+                               CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_ENABLE_OBJC_WEAK = YES;
+                               CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+                               CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_COMMA = YES;
+                               CLANG_WARN_CONSTANT_CONVERSION = YES;
+                               CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                               CLANG_WARN_EMPTY_BODY = YES;
+                               CLANG_WARN_ENUM_CONVERSION = YES;
+                               CLANG_WARN_INFINITE_RECURSION = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+                               CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+                               CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                               CLANG_WARN_STRICT_PROTOTYPES = YES;
+                               CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                               CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                               CLANG_WARN_UNREACHABLE_CODE = YES;
+                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                               COPY_PHASE_STRIP = NO;
+                               DEBUG_INFORMATION_FORMAT = dwarf;
+                               DEVELOPMENT_TEAM = M33X987285;
+                               ENABLE_STRICT_OBJC_MSGSEND = YES;
+                               ENABLE_TESTABILITY = YES;
+                               ENABLE_USER_SCRIPT_SANDBOXING = YES;
+                               GCC_C_LANGUAGE_STANDARD = gnu17;
+                               GCC_DYNAMIC_NO_PIC = NO;
+                               GCC_NO_COMMON_BLOCKS = YES;
+                               GCC_OPTIMIZATION_LEVEL = 0;
+                               GCC_PREPROCESSOR_DEFINITIONS = (
+                                       "DEBUG=1",
+                                       "$(inherited)",
+                               );
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNDECLARED_SELECTOR = YES;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GCC_WARN_UNUSED_FUNCTION = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               IPHONEOS_DEPLOYMENT_TARGET = 18.5;
+                               LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+                               MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+                               MTL_FAST_MATH = YES;
+                               ONLY_ACTIVE_ARCH = YES;
+                               SDKROOT = iphoneos;
+                               SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
+                               SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+                       };
+                       name = Debug;
+               };
+               3F887BB32E38D8DD00C98658 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
+                               CLANG_ANALYZER_NONNULL = YES;
+                               CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+                               CLANG_ENABLE_MODULES = YES;
+                               CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_ENABLE_OBJC_WEAK = YES;
+                               CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+                               CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_COMMA = YES;
+                               CLANG_WARN_CONSTANT_CONVERSION = YES;
+                               CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                               CLANG_WARN_EMPTY_BODY = YES;
+                               CLANG_WARN_ENUM_CONVERSION = YES;
+                               CLANG_WARN_INFINITE_RECURSION = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+                               CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+                               CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                               CLANG_WARN_STRICT_PROTOTYPES = YES;
+                               CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                               CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                               CLANG_WARN_UNREACHABLE_CODE = YES;
+                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                               COPY_PHASE_STRIP = NO;
+                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               DEVELOPMENT_TEAM = M33X987285;
+                               ENABLE_NS_ASSERTIONS = NO;
+                               ENABLE_STRICT_OBJC_MSGSEND = YES;
+                               ENABLE_USER_SCRIPT_SANDBOXING = YES;
+                               GCC_C_LANGUAGE_STANDARD = gnu17;
+                               GCC_NO_COMMON_BLOCKS = YES;
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNDECLARED_SELECTOR = YES;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GCC_WARN_UNUSED_FUNCTION = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               IPHONEOS_DEPLOYMENT_TARGET = 18.5;
+                               LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
+                               MTL_ENABLE_DEBUG_INFO = NO;
+                               MTL_FAST_MATH = YES;
+                               SDKROOT = iphoneos;
+                               SWIFT_COMPILATION_MODE = wholemodule;
+                               VALIDATE_PRODUCT = YES;
+                       };
+                       name = Release;
+               };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+               3F887B972E38D8DC00C98658 /* Build configuration list for PBXProject "LingQi" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               3F887BB22E38D8DD00C98658 /* Debug */,
+                               3F887BB32E38D8DD00C98658 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               3F887BAF2E38D8DD00C98658 /* Build configuration list for PBXNativeTarget "LingQi" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               3F887BB02E38D8DD00C98658 /* Debug */,
+                               3F887BB12E38D8DD00C98658 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+/* End XCConfigurationList section */
+       };
+       rootObject = 3F887B942E38D8DC00C98658 /* Project object */;
+}
diff --git a/LingQi/LingQi.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/LingQi/LingQi.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644 (file)
index 0000000..919434a
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:">
+   </FileRef>
+</Workspace>
diff --git a/LingQi/LingQi.xcworkspace/contents.xcworkspacedata b/LingQi/LingQi.xcworkspace/contents.xcworkspacedata
new file mode 100644 (file)
index 0000000..aca36a7
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "group:LingQi.xcodeproj">
+   </FileRef>
+   <FileRef
+      location = "group:Pods/Pods.xcodeproj">
+   </FileRef>
+</Workspace>
diff --git a/LingQi/LingQi/Api/HttpClient.swift b/LingQi/LingQi/Api/HttpClient.swift
new file mode 100644 (file)
index 0000000..a42e302
--- /dev/null
@@ -0,0 +1,115 @@
+//
+//  Client.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/9.
+//
+
+import Foundation
+import Moya
+import HandyJSON
+
+// 相关api
+enum CommomApi
+{
+    case sms(phone:String)
+    case list(pageNO: Int = 1, pageSize: Int = 10)
+    case login(phone:String,code:String)
+}
+
+// 实现TargetType协议
+extension CommomApi: TargetType
+{
+    // url
+    var baseURL: URL
+    {
+        return URL(string: "https://app-api.raisound.com")!
+    }
+
+    /// 请求路径
+    var path: String {
+        switch self {
+        case .sms(let phone):
+            return "/sys/sms/reg-login/\(phone)"
+        case .list:
+            return "list"
+        case .login(_,_):
+            return "/uc/phone/reg-login"
+        }
+    }
+    
+    /// 请求方式
+    var method: Moya.Method {
+        switch self {
+        case .sms(_):
+            return .get
+        case .login(_,_):
+            return .post
+        default:
+            return .get
+        }
+    }
+    
+    /// 解析格式
+    var sampleData: Data {
+        return "{}".data(using: String.Encoding.utf8)!
+    }
+//https://sz.58.com/esf-ajax/activity/ashen_switch/?city_id=4
+    
+    var task: Task {
+        // 公共参数
+        var params: [String: Any] = ["token": "Gz1qYLXeBW8MZuUfDlr9wsAYuVS1cZFMJY9BbaF842L2gRps747o4w=="]
+        
+        // 收集参数
+        switch self {
+        case let .list(pageNO, pageSize):
+            params["pageNO"] = pageNO
+            params["pageSize"] = pageSize
+        case let .login(phone,code):
+            params["phone"] = phone
+            params["smsCode"] = code
+            break
+        default: break
+        }
+        // 发起请求
+        return .requestParameters(parameters: params, encoding: URLEncoding.default)
+    }
+    
+    /// 公共请求头
+    var headers: [String : String]? {
+        return ["devtype": "iOS", "devid": UIDevice().identifierForVendor?.uuidString ?? "unknow"]
+    }
+
+    
+//https://gz.fang.anjuke.com/xinfang/harmony/adviser/adviser/getMainAdviserBlock?client_source=3&limit=100&target_id=523085&target_type=1&adviser_id=&adviser_type=1&loupan_id=523085&layout_id=&page_source=2
+}
+
+class HttpClient{
+    static let instance = HttpClient()
+    let provider = MoyaProvider<CommomApi>()
+    func request<T: HandyJSON>(_ target: CommomApi,completionHandler:@escaping ((T, String) -> Void)){
+        
+        provider.request(target){ (response) in
+            switch response {
+            case .success(let value):
+                let data = value.data
+//                print("reponse data=>",data.hexEncodedString())
+                var responseStr = "response转字符串失败"
+                if let str = String(data: data, encoding: .utf8) {
+                    responseStr = str
+                }
+                print("reponse text=>",responseStr)
+                if let res = T.deserialize(from: responseStr){
+                    completionHandler(res,responseStr)
+                    return
+                }
+                completionHandler(ResponseBaseModel() as! T,"解析请求失败")
+                break
+            case .failure(let error):
+                completionHandler(ResponseBaseModel() as! T,"请求失败")
+                print("***************\n网络连接失败!\n\(error)\n********************")
+            }
+        }
+    }
+   
+}
diff --git a/LingQi/LingQi/Api/ResponseBaseModel.swift b/LingQi/LingQi/Api/ResponseBaseModel.swift
new file mode 100644 (file)
index 0000000..a56f0d2
--- /dev/null
@@ -0,0 +1,19 @@
+//
+//  BaseResponseModel.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/9.
+//
+
+import Foundation
+import HandyJSON
+public class ResponseBaseModel: HandyJSON {
+    required public init() { }
+
+    public var code = -1
+    public var status = 0
+    public var msg = "请求失败"
+    
+
+    public var isSuccess: Bool { return code == 20000}
+}
diff --git a/LingQi/LingQi/AppDelegate.swift b/LingQi/LingQi/AppDelegate.swift
new file mode 100644 (file)
index 0000000..29649ef
--- /dev/null
@@ -0,0 +1,35 @@
+//
+//  AppDelegate.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/29.
+//
+
+import UIKit
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+
+
+    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+        // Override point for customization after application launch.
+        return true
+    }
+
+    // MARK: UISceneSession Lifecycle
+
+    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
+        // Called when a new scene session is being created.
+        // Use this method to select a configuration to create the new scene with.
+        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
+    }
+
+    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
+        // Called when the user discards a scene session.
+        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
+        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
+    }
+
+
+}
+
diff --git a/LingQi/LingQi/Assets.xcassets/AccentColor.colorset/Contents.json b/LingQi/LingQi/Assets.xcassets/AccentColor.colorset/Contents.json
new file mode 100644 (file)
index 0000000..eb87897
--- /dev/null
@@ -0,0 +1,11 @@
+{
+  "colors" : [
+    {
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/AppIcon.appiconset/Contents.json b/LingQi/LingQi/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644 (file)
index 0000000..2305880
--- /dev/null
@@ -0,0 +1,35 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "platform" : "ios",
+      "size" : "1024x1024"
+    },
+    {
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "dark"
+        }
+      ],
+      "idiom" : "universal",
+      "platform" : "ios",
+      "size" : "1024x1024"
+    },
+    {
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "tinted"
+        }
+      ],
+      "idiom" : "universal",
+      "platform" : "ios",
+      "size" : "1024x1024"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/Contents.json b/LingQi/LingQi/Assets.xcassets/Contents.json
new file mode 100644 (file)
index 0000000..73c0059
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/Contents.json b/LingQi/LingQi/Assets.xcassets/an/Contents.json
new file mode 100644 (file)
index 0000000..73c0059
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/bg_base.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/bg_base.imageset/Contents.json
new file mode 100644 (file)
index 0000000..6766429
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "bg_base.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/bg_base.imageset/bg_base.png b/LingQi/LingQi/Assets.xcassets/an/bg_base.imageset/bg_base.png
new file mode 100644 (file)
index 0000000..4abebc3
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/bg_base.imageset/bg_base.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/bg_login.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/bg_login.imageset/Contents.json
new file mode 100644 (file)
index 0000000..a177303
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "bg_login.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/bg_login.imageset/bg_login.png b/LingQi/LingQi/Assets.xcassets/an/bg_login.imageset/bg_login.png
new file mode 100644 (file)
index 0000000..4abebc3
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/bg_login.imageset/bg_login.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/bg_mine_order.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/bg_mine_order.imageset/Contents.json
new file mode 100644 (file)
index 0000000..42e2d1d
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "bg_mine_order.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/bg_mine_order.imageset/bg_mine_order.png b/LingQi/LingQi/Assets.xcassets/an/bg_mine_order.imageset/bg_mine_order.png
new file mode 100644 (file)
index 0000000..6c31d88
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/bg_mine_order.imageset/bg_mine_order.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/bg_mine_order2.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/bg_mine_order2.imageset/Contents.json
new file mode 100644 (file)
index 0000000..8b90f20
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "bg_mine_order2.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/bg_mine_order2.imageset/bg_mine_order2.png b/LingQi/LingQi/Assets.xcassets/an/bg_mine_order2.imageset/bg_mine_order2.png
new file mode 100644 (file)
index 0000000..821c18e
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/bg_mine_order2.imageset/bg_mine_order2.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/bg_splash.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/bg_splash.imageset/Contents.json
new file mode 100644 (file)
index 0000000..65cc863
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "bg_splash.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/bg_splash.imageset/bg_splash.png b/LingQi/LingQi/Assets.xcassets/an/bg_splash.imageset/bg_splash.png
new file mode 100644 (file)
index 0000000..7bce36c
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/bg_splash.imageset/bg_splash.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/dialog_bg.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/dialog_bg.imageset/Contents.json
new file mode 100644 (file)
index 0000000..e865ee3
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "dialog_bg.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/dialog_bg.imageset/dialog_bg.png b/LingQi/LingQi/Assets.xcassets/an/dialog_bg.imageset/dialog_bg.png
new file mode 100644 (file)
index 0000000..3609e20
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/dialog_bg.imageset/dialog_bg.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/dialog_bg_2.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/dialog_bg_2.imageset/Contents.json
new file mode 100644 (file)
index 0000000..eea521f
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "dialog_bg_2.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/dialog_bg_2.imageset/dialog_bg_2.png b/LingQi/LingQi/Assets.xcassets/an/dialog_bg_2.imageset/dialog_bg_2.png
new file mode 100644 (file)
index 0000000..33255ee
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/dialog_bg_2.imageset/dialog_bg_2.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_ai_config.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_ai_config.imageset/Contents.json
new file mode 100644 (file)
index 0000000..d78f4b4
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_ai_config.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_ai_config.imageset/ic_ai_config.png b/LingQi/LingQi/Assets.xcassets/an/ic_ai_config.imageset/ic_ai_config.png
new file mode 100644 (file)
index 0000000..1f5f705
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_ai_config.imageset/ic_ai_config.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_break.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_break.imageset/Contents.json
new file mode 100644 (file)
index 0000000..61050d3
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_break.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_break.imageset/ic_break.png b/LingQi/LingQi/Assets.xcassets/an/ic_break.imageset/ic_break.png
new file mode 100644 (file)
index 0000000..c2e5cde
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_break.imageset/ic_break.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_check.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_check.imageset/Contents.json
new file mode 100644 (file)
index 0000000..6b9f721
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_check.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_check.imageset/ic_check.png b/LingQi/LingQi/Assets.xcassets/an/ic_check.imageset/ic_check.png
new file mode 100644 (file)
index 0000000..4dff75a
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_check.imageset/ic_check.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_connect_link.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_connect_link.imageset/Contents.json
new file mode 100644 (file)
index 0000000..46bab63
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_connect_link.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_connect_link.imageset/ic_connect_link.png b/LingQi/LingQi/Assets.xcassets/an/ic_connect_link.imageset/ic_connect_link.png
new file mode 100644 (file)
index 0000000..dbc4d0b
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_connect_link.imageset/ic_connect_link.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_connect_log.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_connect_log.imageset/Contents.json
new file mode 100644 (file)
index 0000000..12839ef
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_connect_log.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_connect_log.imageset/ic_connect_log.png b/LingQi/LingQi/Assets.xcassets/an/ic_connect_log.imageset/ic_connect_log.png
new file mode 100644 (file)
index 0000000..c397397
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_connect_log.imageset/ic_connect_log.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_connect_log1.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_connect_log1.imageset/Contents.json
new file mode 100644 (file)
index 0000000..bd2fa29
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_connect_log1.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_connect_log1.imageset/ic_connect_log1.png b/LingQi/LingQi/Assets.xcassets/an/ic_connect_log1.imageset/ic_connect_log1.png
new file mode 100644 (file)
index 0000000..b7dbcb5
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_connect_log1.imageset/ic_connect_log1.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_connect_product.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_connect_product.imageset/Contents.json
new file mode 100644 (file)
index 0000000..5fba3c0
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_connect_product.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_connect_product.imageset/ic_connect_product.png b/LingQi/LingQi/Assets.xcassets/an/ic_connect_product.imageset/ic_connect_product.png
new file mode 100644 (file)
index 0000000..7df4372
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_connect_product.imageset/ic_connect_product.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_connect_product1.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_connect_product1.imageset/Contents.json
new file mode 100644 (file)
index 0000000..74788c5
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_connect_product1.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_connect_product1.imageset/ic_connect_product1.png b/LingQi/LingQi/Assets.xcassets/an/ic_connect_product1.imageset/ic_connect_product1.png
new file mode 100644 (file)
index 0000000..5921750
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_connect_product1.imageset/ic_connect_product1.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_device_set.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_device_set.imageset/Contents.json
new file mode 100644 (file)
index 0000000..5fde870
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_device_set.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_device_set.imageset/ic_device_set.png b/LingQi/LingQi/Assets.xcassets/an/ic_device_set.imageset/ic_device_set.png
new file mode 100644 (file)
index 0000000..7565be3
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_device_set.imageset/ic_device_set.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_dui.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_dui.imageset/Contents.json
new file mode 100644 (file)
index 0000000..50b6af5
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_dui.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_dui.imageset/ic_dui.png b/LingQi/LingQi/Assets.xcassets/an/ic_dui.imageset/ic_dui.png
new file mode 100644 (file)
index 0000000..24d645d
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_dui.imageset/ic_dui.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_edit.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_edit.imageset/Contents.json
new file mode 100644 (file)
index 0000000..123849f
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_edit.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_edit.imageset/ic_edit.png b/LingQi/LingQi/Assets.xcassets/an/ic_edit.imageset/ic_edit.png
new file mode 100644 (file)
index 0000000..f669860
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_edit.imageset/ic_edit.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_false.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_false.imageset/Contents.json
new file mode 100644 (file)
index 0000000..1ca784a
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_false.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_false.imageset/ic_false.png b/LingQi/LingQi/Assets.xcassets/an/ic_false.imageset/ic_false.png
new file mode 100644 (file)
index 0000000..63cba3f
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_false.imageset/ic_false.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_finger.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_finger.imageset/Contents.json
new file mode 100644 (file)
index 0000000..1d0e3ca
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_finger.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_finger.imageset/ic_finger.png b/LingQi/LingQi/Assets.xcassets/an/ic_finger.imageset/ic_finger.png
new file mode 100644 (file)
index 0000000..564c53b
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_finger.imageset/ic_finger.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_add.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_home_add.imageset/Contents.json
new file mode 100644 (file)
index 0000000..5012820
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_home_add.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_add.imageset/ic_home_add.png b/LingQi/LingQi/Assets.xcassets/an/ic_home_add.imageset/ic_home_add.png
new file mode 100644 (file)
index 0000000..7f6f775
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_home_add.imageset/ic_home_add.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_home.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_home_home.imageset/Contents.json
new file mode 100644 (file)
index 0000000..9d77527
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_home_home.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_home.imageset/ic_home_home.png b/LingQi/LingQi/Assets.xcassets/an/ic_home_home.imageset/ic_home_home.png
new file mode 100644 (file)
index 0000000..0d15721
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_home_home.imageset/ic_home_home.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_home_sel.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_home_home_sel.imageset/Contents.json
new file mode 100644 (file)
index 0000000..7d91207
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_home_home_sel.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_home_sel.imageset/ic_home_home_sel.png b/LingQi/LingQi/Assets.xcassets/an/ic_home_home_sel.imageset/ic_home_home_sel.png
new file mode 100644 (file)
index 0000000..5dafc99
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_home_home_sel.imageset/ic_home_home_sel.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_mine.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_home_mine.imageset/Contents.json
new file mode 100644 (file)
index 0000000..3a5c62c
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_home_mine.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_mine.imageset/ic_home_mine.png b/LingQi/LingQi/Assets.xcassets/an/ic_home_mine.imageset/ic_home_mine.png
new file mode 100644 (file)
index 0000000..550b4f9
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_home_mine.imageset/ic_home_mine.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_mine_sel.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_home_mine_sel.imageset/Contents.json
new file mode 100644 (file)
index 0000000..63783aa
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_home_mine_sel.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_mine_sel.imageset/ic_home_mine_sel.png b/LingQi/LingQi/Assets.xcassets/an/ic_home_mine_sel.imageset/ic_home_mine_sel.png
new file mode 100644 (file)
index 0000000..a3134c4
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_home_mine_sel.imageset/ic_home_mine_sel.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_nodevice.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_home_nodevice.imageset/Contents.json
new file mode 100644 (file)
index 0000000..6efbd6a
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_home_nodevice.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_nodevice.imageset/ic_home_nodevice.png b/LingQi/LingQi/Assets.xcassets/an/ic_home_nodevice.imageset/ic_home_nodevice.png
new file mode 100644 (file)
index 0000000..183e629
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_home_nodevice.imageset/ic_home_nodevice.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_scan.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_home_scan.imageset/Contents.json
new file mode 100644 (file)
index 0000000..7077852
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_home_scan.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_scan.imageset/ic_home_scan.png b/LingQi/LingQi/Assets.xcassets/an/ic_home_scan.imageset/ic_home_scan.png
new file mode 100644 (file)
index 0000000..99047ce
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_home_scan.imageset/ic_home_scan.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_tv.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_home_tv.imageset/Contents.json
new file mode 100644 (file)
index 0000000..d025cde
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_home_tv.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_home_tv.imageset/ic_home_tv.png b/LingQi/LingQi/Assets.xcassets/an/ic_home_tv.imageset/ic_home_tv.png
new file mode 100644 (file)
index 0000000..270f341
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_home_tv.imageset/ic_home_tv.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_link.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_link.imageset/Contents.json
new file mode 100644 (file)
index 0000000..350aa96
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_link.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_link.imageset/ic_link.png b/LingQi/LingQi/Assets.xcassets/an/ic_link.imageset/ic_link.png
new file mode 100644 (file)
index 0000000..c70fbdb
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_link.imageset/ic_link.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_linked.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_linked.imageset/Contents.json
new file mode 100644 (file)
index 0000000..ce89a45
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_linked.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_linked.imageset/ic_linked.png b/LingQi/LingQi/Assets.xcassets/an/ic_linked.imageset/ic_linked.png
new file mode 100644 (file)
index 0000000..db4ee36
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_linked.imageset/ic_linked.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_logo.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_logo.imageset/Contents.json
new file mode 100644 (file)
index 0000000..301eaaa
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_logo.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_logo.imageset/ic_logo.png b/LingQi/LingQi/Assets.xcassets/an/ic_logo.imageset/ic_logo.png
new file mode 100644 (file)
index 0000000..d9c726b
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_logo.imageset/ic_logo.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_mac.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_mac.imageset/Contents.json
new file mode 100644 (file)
index 0000000..6454deb
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_mac.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_mac.imageset/ic_mac.png b/LingQi/LingQi/Assets.xcassets/an/ic_mac.imageset/ic_mac.png
new file mode 100644 (file)
index 0000000..3df7fe5
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_mac.imageset/ic_mac.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_man.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_man.imageset/Contents.json
new file mode 100644 (file)
index 0000000..9ca6fff
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_man.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_man.imageset/ic_man.png b/LingQi/LingQi/Assets.xcassets/an/ic_man.imageset/ic_man.png
new file mode 100644 (file)
index 0000000..83f643c
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_man.imageset/ic_man.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_mine_1.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_mine_1.imageset/Contents.json
new file mode 100644 (file)
index 0000000..ea401dc
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_mine_1.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_mine_1.imageset/ic_mine_1.png b/LingQi/LingQi/Assets.xcassets/an/ic_mine_1.imageset/ic_mine_1.png
new file mode 100644 (file)
index 0000000..543b9f4
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_mine_1.imageset/ic_mine_1.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_mine_2.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_mine_2.imageset/Contents.json
new file mode 100644 (file)
index 0000000..ca9a119
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_mine_2.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_mine_2.imageset/ic_mine_2.png b/LingQi/LingQi/Assets.xcassets/an/ic_mine_2.imageset/ic_mine_2.png
new file mode 100644 (file)
index 0000000..df0606e
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_mine_2.imageset/ic_mine_2.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_mine_3.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_mine_3.imageset/Contents.json
new file mode 100644 (file)
index 0000000..2b04ada
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_mine_3.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_mine_3.imageset/ic_mine_3.png b/LingQi/LingQi/Assets.xcassets/an/ic_mine_3.imageset/ic_mine_3.png
new file mode 100644 (file)
index 0000000..ad39548
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_mine_3.imageset/ic_mine_3.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_more.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_more.imageset/Contents.json
new file mode 100644 (file)
index 0000000..9012365
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_more.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_more.imageset/ic_more.png b/LingQi/LingQi/Assets.xcassets/an/ic_more.imageset/ic_more.png
new file mode 100644 (file)
index 0000000..7c3f28a
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_more.imageset/ic_more.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_more2.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_more2.imageset/Contents.json
new file mode 100644 (file)
index 0000000..5b7ebe8
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_more2.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_more2.imageset/ic_more2.png b/LingQi/LingQi/Assets.xcassets/an/ic_more2.imageset/ic_more2.png
new file mode 100644 (file)
index 0000000..327b014
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_more2.imageset/ic_more2.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_msg_recoder.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_msg_recoder.imageset/Contents.json
new file mode 100644 (file)
index 0000000..3711e46
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_msg_recoder.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_msg_recoder.imageset/ic_msg_recoder.png b/LingQi/LingQi/Assets.xcassets/an/ic_msg_recoder.imageset/ic_msg_recoder.png
new file mode 100644 (file)
index 0000000..fd1393f
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_msg_recoder.imageset/ic_msg_recoder.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_nopub.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_nopub.imageset/Contents.json
new file mode 100644 (file)
index 0000000..d174291
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_nopub.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_nopub.imageset/ic_nopub.png b/LingQi/LingQi/Assets.xcassets/an/ic_nopub.imageset/ic_nopub.png
new file mode 100644 (file)
index 0000000..179920f
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_nopub.imageset/ic_nopub.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_power.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_power.imageset/Contents.json
new file mode 100644 (file)
index 0000000..880a0b0
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_power.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_power.imageset/ic_power.png b/LingQi/LingQi/Assets.xcassets/an/ic_power.imageset/ic_power.png
new file mode 100644 (file)
index 0000000..25ec4ca
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_power.imageset/ic_power.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_product.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_product.imageset/Contents.json
new file mode 100644 (file)
index 0000000..46e23a3
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_product.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_product.imageset/ic_product.png b/LingQi/LingQi/Assets.xcassets/an/ic_product.imageset/ic_product.png
new file mode 100644 (file)
index 0000000..47ca72e
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_product.imageset/ic_product.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_remainber.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_remainber.imageset/Contents.json
new file mode 100644 (file)
index 0000000..302190f
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_remainber.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_remainber.imageset/ic_remainber.png b/LingQi/LingQi/Assets.xcassets/an/ic_remainber.imageset/ic_remainber.png
new file mode 100644 (file)
index 0000000..c63c630
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_remainber.imageset/ic_remainber.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_role.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_role.imageset/Contents.json
new file mode 100644 (file)
index 0000000..5137c7e
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_role.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_role.imageset/ic_role.png b/LingQi/LingQi/Assets.xcassets/an/ic_role.imageset/ic_role.png
new file mode 100644 (file)
index 0000000..d6e6ba3
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_role.imageset/ic_role.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_scam.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_scam.imageset/Contents.json
new file mode 100644 (file)
index 0000000..63367d1
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_scam.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_scam.imageset/ic_scam.png b/LingQi/LingQi/Assets.xcassets/an/ic_scam.imageset/ic_scam.png
new file mode 100644 (file)
index 0000000..99047ce
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_scam.imageset/ic_scam.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_seach.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_seach.imageset/Contents.json
new file mode 100644 (file)
index 0000000..0af1df6
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_seach.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_seach.imageset/ic_seach.png b/LingQi/LingQi/Assets.xcassets/an/ic_seach.imageset/ic_seach.png
new file mode 100644 (file)
index 0000000..7db0a19
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_seach.imageset/ic_seach.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_speak.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_speak.imageset/Contents.json
new file mode 100644 (file)
index 0000000..7b79d42
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_speak.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_speak.imageset/ic_speak.png b/LingQi/LingQi/Assets.xcassets/an/ic_speak.imageset/ic_speak.png
new file mode 100644 (file)
index 0000000..1cbb8a0
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_speak.imageset/ic_speak.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_speek.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_speek.imageset/Contents.json
new file mode 100644 (file)
index 0000000..d28a1f9
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_speek.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_speek.imageset/ic_speek.png b/LingQi/LingQi/Assets.xcassets/an/ic_speek.imageset/ic_speek.png
new file mode 100644 (file)
index 0000000..766941f
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_speek.imageset/ic_speek.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_sure.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_sure.imageset/Contents.json
new file mode 100644 (file)
index 0000000..1c551a2
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_sure.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_sure.imageset/ic_sure.png b/LingQi/LingQi/Assets.xcassets/an/ic_sure.imageset/ic_sure.png
new file mode 100644 (file)
index 0000000..930d62d
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_sure.imageset/ic_sure.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_tip.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_tip.imageset/Contents.json
new file mode 100644 (file)
index 0000000..8111a5b
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_tip.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_tip.imageset/ic_tip.png b/LingQi/LingQi/Assets.xcassets/an/ic_tip.imageset/ic_tip.png
new file mode 100644 (file)
index 0000000..f60df48
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_tip.imageset/ic_tip.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_unlink.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_unlink.imageset/Contents.json
new file mode 100644 (file)
index 0000000..9f5415f
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_unlink.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_unlink.imageset/ic_unlink.png b/LingQi/LingQi/Assets.xcassets/an/ic_unlink.imageset/ic_unlink.png
new file mode 100644 (file)
index 0000000..7ac0399
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_unlink.imageset/ic_unlink.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_user.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_user.imageset/Contents.json
new file mode 100644 (file)
index 0000000..b93e673
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_user.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_user.imageset/ic_user.png b/LingQi/LingQi/Assets.xcassets/an/ic_user.imageset/ic_user.png
new file mode 100644 (file)
index 0000000..6df0916
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_user.imageset/ic_user.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_vip_year.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_vip_year.imageset/Contents.json
new file mode 100644 (file)
index 0000000..8534088
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_vip_year.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_vip_year.imageset/ic_vip_year.png b/LingQi/LingQi/Assets.xcassets/an/ic_vip_year.imageset/ic_vip_year.png
new file mode 100644 (file)
index 0000000..32219f8
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_vip_year.imageset/ic_vip_year.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_voice.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_voice.imageset/Contents.json
new file mode 100644 (file)
index 0000000..b0cde55
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_voice.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_voice.imageset/ic_voice.png b/LingQi/LingQi/Assets.xcassets/an/ic_voice.imageset/ic_voice.png
new file mode 100644 (file)
index 0000000..5373980
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_voice.imageset/ic_voice.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_voice_jia.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_voice_jia.imageset/Contents.json
new file mode 100644 (file)
index 0000000..3b01221
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_voice_jia.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_voice_jia.imageset/ic_voice_jia.png b/LingQi/LingQi/Assets.xcassets/an/ic_voice_jia.imageset/ic_voice_jia.png
new file mode 100644 (file)
index 0000000..bec62a4
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_voice_jia.imageset/ic_voice_jia.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_voice_jian.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_voice_jian.imageset/Contents.json
new file mode 100644 (file)
index 0000000..0713580
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_voice_jian.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_voice_jian.imageset/ic_voice_jian.png b/LingQi/LingQi/Assets.xcassets/an/ic_voice_jian.imageset/ic_voice_jian.png
new file mode 100644 (file)
index 0000000..d97369a
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_voice_jian.imageset/ic_voice_jian.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_wifi1.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_wifi1.imageset/Contents.json
new file mode 100644 (file)
index 0000000..91c5dfc
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_wifi1.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_wifi1.imageset/ic_wifi1.png b/LingQi/LingQi/Assets.xcassets/an/ic_wifi1.imageset/ic_wifi1.png
new file mode 100644 (file)
index 0000000..6558488
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_wifi1.imageset/ic_wifi1.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_wifi2.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_wifi2.imageset/Contents.json
new file mode 100644 (file)
index 0000000..eaa7d20
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_wifi2.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_wifi2.imageset/ic_wifi2.png b/LingQi/LingQi/Assets.xcassets/an/ic_wifi2.imageset/ic_wifi2.png
new file mode 100644 (file)
index 0000000..5244b23
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_wifi2.imageset/ic_wifi2.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_wifi3.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_wifi3.imageset/Contents.json
new file mode 100644 (file)
index 0000000..00a14bd
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_wifi3.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_wifi3.imageset/ic_wifi3.png b/LingQi/LingQi/Assets.xcassets/an/ic_wifi3.imageset/ic_wifi3.png
new file mode 100644 (file)
index 0000000..5244b23
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_wifi3.imageset/ic_wifi3.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_wifi4.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_wifi4.imageset/Contents.json
new file mode 100644 (file)
index 0000000..ef6b388
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_wifi4.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_wifi4.imageset/ic_wifi4.png b/LingQi/LingQi/Assets.xcassets/an/ic_wifi4.imageset/ic_wifi4.png
new file mode 100644 (file)
index 0000000..fdc21db
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_wifi4.imageset/ic_wifi4.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_woman.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_woman.imageset/Contents.json
new file mode 100644 (file)
index 0000000..555340d
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_woman.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_woman.imageset/ic_woman.png b/LingQi/LingQi/Assets.xcassets/an/ic_woman.imageset/ic_woman.png
new file mode 100644 (file)
index 0000000..ee388cf
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_woman.imageset/ic_woman.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_yinse.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/ic_yinse.imageset/Contents.json
new file mode 100644 (file)
index 0000000..7f86ecc
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_yinse.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/ic_yinse.imageset/ic_yinse.png b/LingQi/LingQi/Assets.xcassets/an/ic_yinse.imageset/ic_yinse.png
new file mode 100644 (file)
index 0000000..fd36fa1
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/ic_yinse.imageset/ic_yinse.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/loading.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/loading.imageset/Contents.json
new file mode 100644 (file)
index 0000000..10a4d43
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "loading.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/loading.imageset/loading.png b/LingQi/LingQi/Assets.xcassets/an/loading.imageset/loading.png
new file mode 100644 (file)
index 0000000..ad89ca1
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/loading.imageset/loading.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/an/splash_tv.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/an/splash_tv.imageset/Contents.json
new file mode 100644 (file)
index 0000000..525073d
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "splash_tv.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/an/splash_tv.imageset/splash_tv.png b/LingQi/LingQi/Assets.xcassets/an/splash_tv.imageset/splash_tv.png
new file mode 100644 (file)
index 0000000..5e82271
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/an/splash_tv.imageset/splash_tv.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/081_发现.imageset/081_发现.png b/LingQi/LingQi/Assets.xcassets/home/081_发现.imageset/081_发现.png
new file mode 100644 (file)
index 0000000..c40687b
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/081_\345\217\221\347\216\260.imageset/081_\345\217\221\347\216\260.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/081_发现.imageset/081_发现@2x.png b/LingQi/LingQi/Assets.xcassets/home/081_发现.imageset/081_发现@2x.png
new file mode 100644 (file)
index 0000000..7a797e4
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/081_\345\217\221\347\216\260.imageset/081_\345\217\221\347\216\260@2x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/081_发现.imageset/081_发现@3x.png b/LingQi/LingQi/Assets.xcassets/home/081_发现.imageset/081_发现@3x.png
new file mode 100644 (file)
index 0000000..5b331d3
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/081_\345\217\221\347\216\260.imageset/081_\345\217\221\347\216\260@3x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/081_发现.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/home/081_发现.imageset/Contents.json
new file mode 100644 (file)
index 0000000..15635ff
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "081_发现.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "081_发现@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "081_发现@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/home/Contents.json b/LingQi/LingQi/Assets.xcassets/home/Contents.json
new file mode 100644 (file)
index 0000000..73c0059
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/home/Frame 134.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/home/Frame 134.imageset/Contents.json
new file mode 100644 (file)
index 0000000..944c2cb
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Frame 134.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Frame 134@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Frame 134@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/home/Frame 134.imageset/Frame 134.png b/LingQi/LingQi/Assets.xcassets/home/Frame 134.imageset/Frame 134.png
new file mode 100644 (file)
index 0000000..e02bb67
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/home/Frame 134.imageset/Frame 134.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/Frame 134.imageset/Frame 134@2x.png b/LingQi/LingQi/Assets.xcassets/home/Frame 134.imageset/Frame 134@2x.png
new file mode 100644 (file)
index 0000000..9f4e42b
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/home/Frame 134.imageset/Frame 134@2x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/Frame 134.imageset/Frame 134@3x.png b/LingQi/LingQi/Assets.xcassets/home/Frame 134.imageset/Frame 134@3x.png
new file mode 100644 (file)
index 0000000..25c03b1
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/home/Frame 134.imageset/Frame 134@3x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/Frame 220.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/home/Frame 220.imageset/Contents.json
new file mode 100644 (file)
index 0000000..3ed7a02
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Frame 220.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Frame 220@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Frame 220@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/home/Frame 220.imageset/Frame 220.png b/LingQi/LingQi/Assets.xcassets/home/Frame 220.imageset/Frame 220.png
new file mode 100644 (file)
index 0000000..3f62fcd
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/home/Frame 220.imageset/Frame 220.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/Frame 220.imageset/Frame 220@2x.png b/LingQi/LingQi/Assets.xcassets/home/Frame 220.imageset/Frame 220@2x.png
new file mode 100644 (file)
index 0000000..8d54b72
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/home/Frame 220.imageset/Frame 220@2x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/Frame 220.imageset/Frame 220@3x.png b/LingQi/LingQi/Assets.xcassets/home/Frame 220.imageset/Frame 220@3x.png
new file mode 100644 (file)
index 0000000..51c3c3a
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/home/Frame 220.imageset/Frame 220@3x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/Group 347.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/home/Group 347.imageset/Contents.json
new file mode 100644 (file)
index 0000000..ecfabe9
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Group 347.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Group 347@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Group 347@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/home/Group 347.imageset/Group 347.png b/LingQi/LingQi/Assets.xcassets/home/Group 347.imageset/Group 347.png
new file mode 100644 (file)
index 0000000..1b9025d
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/home/Group 347.imageset/Group 347.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/Group 347.imageset/Group 347@2x.png b/LingQi/LingQi/Assets.xcassets/home/Group 347.imageset/Group 347@2x.png
new file mode 100644 (file)
index 0000000..b36e6d5
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/home/Group 347.imageset/Group 347@2x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/Group 347.imageset/Group 347@3x.png b/LingQi/LingQi/Assets.xcassets/home/Group 347.imageset/Group 347@3x.png
new file mode 100644 (file)
index 0000000..2538ebc
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/home/Group 347.imageset/Group 347@3x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/Group 352.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/home/Group 352.imageset/Contents.json
new file mode 100644 (file)
index 0000000..3c2949a
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Group 352.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Group 352@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Group 352@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/home/Group 352.imageset/Group 352.png b/LingQi/LingQi/Assets.xcassets/home/Group 352.imageset/Group 352.png
new file mode 100644 (file)
index 0000000..92b6c57
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/home/Group 352.imageset/Group 352.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/Group 352.imageset/Group 352@2x.png b/LingQi/LingQi/Assets.xcassets/home/Group 352.imageset/Group 352@2x.png
new file mode 100644 (file)
index 0000000..118c0d7
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/home/Group 352.imageset/Group 352@2x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/Group 352.imageset/Group 352@3x.png b/LingQi/LingQi/Assets.xcassets/home/Group 352.imageset/Group 352@3x.png
new file mode 100644 (file)
index 0000000..47561b6
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/home/Group 352.imageset/Group 352@3x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_0_normal.imageset/081_主页.png b/LingQi/LingQi/Assets.xcassets/home/tab_0_normal.imageset/081_主页.png
new file mode 100644 (file)
index 0000000..a92d424
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/tab_0_normal.imageset/081_\344\270\273\351\241\265.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_0_normal.imageset/081_主页@2x.png b/LingQi/LingQi/Assets.xcassets/home/tab_0_normal.imageset/081_主页@2x.png
new file mode 100644 (file)
index 0000000..4541a27
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/tab_0_normal.imageset/081_\344\270\273\351\241\265@2x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_0_normal.imageset/081_主页@3x.png b/LingQi/LingQi/Assets.xcassets/home/tab_0_normal.imageset/081_主页@3x.png
new file mode 100644 (file)
index 0000000..5a29c1c
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/tab_0_normal.imageset/081_\344\270\273\351\241\265@3x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_0_normal.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/home/tab_0_normal.imageset/Contents.json
new file mode 100644 (file)
index 0000000..c21be7b
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "081_主页.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "081_主页@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "081_主页@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_0_selected.imageset/081_主页.png b/LingQi/LingQi/Assets.xcassets/home/tab_0_selected.imageset/081_主页.png
new file mode 100644 (file)
index 0000000..f91691a
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/tab_0_selected.imageset/081_\344\270\273\351\241\265.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_0_selected.imageset/081_主页@2x.png b/LingQi/LingQi/Assets.xcassets/home/tab_0_selected.imageset/081_主页@2x.png
new file mode 100644 (file)
index 0000000..db6a6ed
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/tab_0_selected.imageset/081_\344\270\273\351\241\265@2x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_0_selected.imageset/081_主页@3x.png b/LingQi/LingQi/Assets.xcassets/home/tab_0_selected.imageset/081_主页@3x.png
new file mode 100644 (file)
index 0000000..1e18885
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/tab_0_selected.imageset/081_\344\270\273\351\241\265@3x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_0_selected.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/home/tab_0_selected.imageset/Contents.json
new file mode 100644 (file)
index 0000000..c21be7b
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "081_主页.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "081_主页@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "081_主页@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_1_normal.imageset/081_我的.png b/LingQi/LingQi/Assets.xcassets/home/tab_1_normal.imageset/081_我的.png
new file mode 100644 (file)
index 0000000..da8e9f3
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/tab_1_normal.imageset/081_\346\210\221\347\232\204.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_1_normal.imageset/081_我的@2x.png b/LingQi/LingQi/Assets.xcassets/home/tab_1_normal.imageset/081_我的@2x.png
new file mode 100644 (file)
index 0000000..bac40a7
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/tab_1_normal.imageset/081_\346\210\221\347\232\204@2x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_1_normal.imageset/081_我的@3x.png b/LingQi/LingQi/Assets.xcassets/home/tab_1_normal.imageset/081_我的@3x.png
new file mode 100644 (file)
index 0000000..50c504c
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/tab_1_normal.imageset/081_\346\210\221\347\232\204@3x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_1_normal.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/home/tab_1_normal.imageset/Contents.json
new file mode 100644 (file)
index 0000000..71388ea
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "081_我的.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "081_我的@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "081_我的@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_1_selected.imageset/081_我的.png b/LingQi/LingQi/Assets.xcassets/home/tab_1_selected.imageset/081_我的.png
new file mode 100644 (file)
index 0000000..1b99f19
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/tab_1_selected.imageset/081_\346\210\221\347\232\204.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_1_selected.imageset/081_我的@2x.png b/LingQi/LingQi/Assets.xcassets/home/tab_1_selected.imageset/081_我的@2x.png
new file mode 100644 (file)
index 0000000..e0e1bf2
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/tab_1_selected.imageset/081_\346\210\221\347\232\204@2x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_1_selected.imageset/081_我的@3x.png b/LingQi/LingQi/Assets.xcassets/home/tab_1_selected.imageset/081_我的@3x.png
new file mode 100644 (file)
index 0000000..85452de
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/tab_1_selected.imageset/081_\346\210\221\347\232\204@3x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/tab_1_selected.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/home/tab_1_selected.imageset/Contents.json
new file mode 100644 (file)
index 0000000..71388ea
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "081_我的.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "081_我的@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "081_我的@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/home/空内容.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/home/空内容.imageset/Contents.json
new file mode 100644 (file)
index 0000000..493fb1a
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "空内容.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "空内容@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "空内容@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/home/空内容.imageset/空内容.png b/LingQi/LingQi/Assets.xcassets/home/空内容.imageset/空内容.png
new file mode 100644 (file)
index 0000000..b13789a
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/\347\251\272\345\206\205\345\256\271.imageset/\347\251\272\345\206\205\345\256\271.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/空内容.imageset/空内容@2x.png b/LingQi/LingQi/Assets.xcassets/home/空内容.imageset/空内容@2x.png
new file mode 100644 (file)
index 0000000..8f4f0f6
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/\347\251\272\345\206\205\345\256\271.imageset/\347\251\272\345\206\205\345\256\271@2x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/home/空内容.imageset/空内容@3x.png b/LingQi/LingQi/Assets.xcassets/home/空内容.imageset/空内容@3x.png
new file mode 100644 (file)
index 0000000..cd8f7f2
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/home/\347\251\272\345\206\205\345\256\271.imageset/\347\251\272\345\206\205\345\256\271@3x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/Contents.json
new file mode 100644 (file)
index 0000000..73c0059
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Frame 1453.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/Frame 1453.imageset/Contents.json
new file mode 100644 (file)
index 0000000..9af40ec
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Frame 1453.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Frame 1453@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Frame 1453@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Frame 1453.imageset/Frame 1453.png b/LingQi/LingQi/Assets.xcassets/mine/Frame 1453.imageset/Frame 1453.png
new file mode 100644 (file)
index 0000000..54d0f5a
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/Frame 1453.imageset/Frame 1453.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Frame 1453.imageset/Frame 1453@2x.png b/LingQi/LingQi/Assets.xcassets/mine/Frame 1453.imageset/Frame 1453@2x.png
new file mode 100644 (file)
index 0000000..04589db
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/Frame 1453.imageset/Frame 1453@2x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Frame 1453.imageset/Frame 1453@3x.png b/LingQi/LingQi/Assets.xcassets/mine/Frame 1453.imageset/Frame 1453@3x.png
new file mode 100644 (file)
index 0000000..73e423e
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/Frame 1453.imageset/Frame 1453@3x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Frame(1).imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/Frame(1).imageset/Contents.json
new file mode 100644 (file)
index 0000000..8eaecc5
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Frame(1).png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Frame@2x(1).png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Frame@3x(1).png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Frame(1).imageset/Frame(1).png b/LingQi/LingQi/Assets.xcassets/mine/Frame(1).imageset/Frame(1).png
new file mode 100644 (file)
index 0000000..587dfb9
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/Frame(1).imageset/Frame(1).png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Frame(1).imageset/Frame@2x(1).png b/LingQi/LingQi/Assets.xcassets/mine/Frame(1).imageset/Frame@2x(1).png
new file mode 100644 (file)
index 0000000..a62288b
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/Frame(1).imageset/Frame@2x(1).png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Frame(1).imageset/Frame@3x(1).png b/LingQi/LingQi/Assets.xcassets/mine/Frame(1).imageset/Frame@3x(1).png
new file mode 100644 (file)
index 0000000..7a8bb8e
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/Frame(1).imageset/Frame@3x(1).png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Frame(2).imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/Frame(2).imageset/Contents.json
new file mode 100644 (file)
index 0000000..115ae44
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Frame(2).png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Frame@2x(2).png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Frame@3x(2).png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Frame(2).imageset/Frame(2).png b/LingQi/LingQi/Assets.xcassets/mine/Frame(2).imageset/Frame(2).png
new file mode 100644 (file)
index 0000000..14c8b3f
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/Frame(2).imageset/Frame(2).png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Frame(2).imageset/Frame@2x(2).png b/LingQi/LingQi/Assets.xcassets/mine/Frame(2).imageset/Frame@2x(2).png
new file mode 100644 (file)
index 0000000..150ba1b
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/Frame(2).imageset/Frame@2x(2).png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Frame(2).imageset/Frame@3x(2).png b/LingQi/LingQi/Assets.xcassets/mine/Frame(2).imageset/Frame@3x(2).png
new file mode 100644 (file)
index 0000000..951c1ef
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/Frame(2).imageset/Frame@3x(2).png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Rectangle 268.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/Rectangle 268.imageset/Contents.json
new file mode 100644 (file)
index 0000000..76beba5
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Rectangle 268.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Rectangle 268@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Rectangle 268@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Rectangle 268.imageset/Rectangle 268.png b/LingQi/LingQi/Assets.xcassets/mine/Rectangle 268.imageset/Rectangle 268.png
new file mode 100644 (file)
index 0000000..cbcd2bc
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/Rectangle 268.imageset/Rectangle 268.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Rectangle 268.imageset/Rectangle 268@2x.png b/LingQi/LingQi/Assets.xcassets/mine/Rectangle 268.imageset/Rectangle 268@2x.png
new file mode 100644 (file)
index 0000000..0ce6ee7
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/Rectangle 268.imageset/Rectangle 268@2x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Rectangle 268.imageset/Rectangle 268@3x.png b/LingQi/LingQi/Assets.xcassets/mine/Rectangle 268.imageset/Rectangle 268@3x.png
new file mode 100644 (file)
index 0000000..cc6947c
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/Rectangle 268.imageset/Rectangle 268@3x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Rectangle 273.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/Rectangle 273.imageset/Contents.json
new file mode 100644 (file)
index 0000000..51c7c57
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Rectangle 273.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Rectangle 273@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Rectangle 273@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Rectangle 273.imageset/Rectangle 273.png b/LingQi/LingQi/Assets.xcassets/mine/Rectangle 273.imageset/Rectangle 273.png
new file mode 100644 (file)
index 0000000..a45dcda
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/Rectangle 273.imageset/Rectangle 273.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Rectangle 273.imageset/Rectangle 273@2x.png b/LingQi/LingQi/Assets.xcassets/mine/Rectangle 273.imageset/Rectangle 273@2x.png
new file mode 100644 (file)
index 0000000..7725c61
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/Rectangle 273.imageset/Rectangle 273@2x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/Rectangle 273.imageset/Rectangle 273@3x.png b/LingQi/LingQi/Assets.xcassets/mine/Rectangle 273.imageset/Rectangle 273@3x.png
new file mode 100644 (file)
index 0000000..7207a57
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/Rectangle 273.imageset/Rectangle 273@3x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/arrow_back.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/arrow_back.imageset/Contents.json
new file mode 100644 (file)
index 0000000..a9337b9
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_back.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/arrow_back.imageset/ic_back.png b/LingQi/LingQi/Assets.xcassets/mine/arrow_back.imageset/ic_back.png
new file mode 100644 (file)
index 0000000..0b3636f
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/arrow_back.imageset/ic_back.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/arrow_next.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/arrow_next.imageset/Contents.json
new file mode 100644 (file)
index 0000000..4886886
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "个人中心-进入 1.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "个人中心-进入 1@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "个人中心-进入 1@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/arrow_next.imageset/个人中心-进入 1.png b/LingQi/LingQi/Assets.xcassets/mine/arrow_next.imageset/个人中心-进入 1.png
new file mode 100644 (file)
index 0000000..50688e6
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/mine/arrow_next.imageset/\344\270\252\344\272\272\344\270\255\345\277\203-\350\277\233\345\205\245 1.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/arrow_next.imageset/个人中心-进入 1@2x.png b/LingQi/LingQi/Assets.xcassets/mine/arrow_next.imageset/个人中心-进入 1@2x.png
new file mode 100644 (file)
index 0000000..5f350c5
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/mine/arrow_next.imageset/\344\270\252\344\272\272\344\270\255\345\277\203-\350\277\233\345\205\245 1@2x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/arrow_next.imageset/个人中心-进入 1@3x.png b/LingQi/LingQi/Assets.xcassets/mine/arrow_next.imageset/个人中心-进入 1@3x.png
new file mode 100644 (file)
index 0000000..f3b7a15
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/mine/arrow_next.imageset/\344\270\252\344\272\272\344\270\255\345\277\203-\350\277\233\345\205\245 1@3x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/image 57.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/image 57.imageset/Contents.json
new file mode 100644 (file)
index 0000000..a53d3e9
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "image 57.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "image 57@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "image 57@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/image 57.imageset/image 57.png b/LingQi/LingQi/Assets.xcassets/mine/image 57.imageset/image 57.png
new file mode 100644 (file)
index 0000000..45c8988
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/image 57.imageset/image 57.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/image 57.imageset/image 57@2x.png b/LingQi/LingQi/Assets.xcassets/mine/image 57.imageset/image 57@2x.png
new file mode 100644 (file)
index 0000000..8716500
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/image 57.imageset/image 57@2x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/image 57.imageset/image 57@3x.png b/LingQi/LingQi/Assets.xcassets/mine/image 57.imageset/image 57@3x.png
new file mode 100644 (file)
index 0000000..c8f8d21
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/image 57.imageset/image 57@3x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/login_cover.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/login_cover.imageset/Contents.json
new file mode 100644 (file)
index 0000000..944c2cb
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Frame 134.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Frame 134@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Frame 134@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/login_cover.imageset/Frame 134.png b/LingQi/LingQi/Assets.xcassets/mine/login_cover.imageset/Frame 134.png
new file mode 100644 (file)
index 0000000..7dc5484
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/login_cover.imageset/Frame 134.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/login_cover.imageset/Frame 134@2x.png b/LingQi/LingQi/Assets.xcassets/mine/login_cover.imageset/Frame 134@2x.png
new file mode 100644 (file)
index 0000000..b81b861
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/login_cover.imageset/Frame 134@2x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/login_cover.imageset/Frame 134@3x.png b/LingQi/LingQi/Assets.xcassets/mine/login_cover.imageset/Frame 134@3x.png
new file mode 100644 (file)
index 0000000..32e6c2d
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/login_cover.imageset/Frame 134@3x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/login_logo.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/login_logo.imageset/Contents.json
new file mode 100644 (file)
index 0000000..4895580
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Group 281.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Group 281@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Group 281@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/login_logo.imageset/Group 281.png b/LingQi/LingQi/Assets.xcassets/mine/login_logo.imageset/Group 281.png
new file mode 100644 (file)
index 0000000..ec96160
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/login_logo.imageset/Group 281.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/login_logo.imageset/Group 281@2x.png b/LingQi/LingQi/Assets.xcassets/mine/login_logo.imageset/Group 281@2x.png
new file mode 100644 (file)
index 0000000..3307d6d
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/login_logo.imageset/Group 281@2x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/login_logo.imageset/Group 281@3x.png b/LingQi/LingQi/Assets.xcassets/mine/login_logo.imageset/Group 281@3x.png
new file mode 100644 (file)
index 0000000..5802893
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/login_logo.imageset/Group 281@3x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_cell_device.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_device.imageset/Contents.json
new file mode 100644 (file)
index 0000000..4b7bf60
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Frame.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Frame@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Frame@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_cell_device.imageset/Frame.png b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_device.imageset/Frame.png
new file mode 100644 (file)
index 0000000..1209ddb
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_device.imageset/Frame.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_cell_device.imageset/Frame@2x.png b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_device.imageset/Frame@2x.png
new file mode 100644 (file)
index 0000000..4ea8812
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_device.imageset/Frame@2x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_cell_device.imageset/Frame@3x.png b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_device.imageset/Frame@3x.png
new file mode 100644 (file)
index 0000000..4bb8033
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_device.imageset/Frame@3x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_cell_product.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_product.imageset/Contents.json
new file mode 100644 (file)
index 0000000..00090de
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "信息.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "信息@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "信息@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_cell_product.imageset/信息.png b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_product.imageset/信息.png
new file mode 100644 (file)
index 0000000..74a03e5
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_product.imageset/\344\277\241\346\201\257.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_cell_product.imageset/信息@2x.png b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_product.imageset/信息@2x.png
new file mode 100644 (file)
index 0000000..0a4a56b
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_product.imageset/\344\277\241\346\201\257@2x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_cell_product.imageset/信息@3x.png b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_product.imageset/信息@3x.png
new file mode 100644 (file)
index 0000000..1d53b3f
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_product.imageset/\344\277\241\346\201\257@3x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_cell_service.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_service.imageset/Contents.json
new file mode 100644 (file)
index 0000000..7f757d8
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "转账.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "转账@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "转账@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_cell_service.imageset/转账.png b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_service.imageset/转账.png
new file mode 100644 (file)
index 0000000..17994e7
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_service.imageset/\350\275\254\350\264\246.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_cell_service.imageset/转账@2x.png b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_service.imageset/转账@2x.png
new file mode 100644 (file)
index 0000000..1648cc3
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_service.imageset/\350\275\254\350\264\246@2x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_cell_service.imageset/转账@3x.png b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_service.imageset/转账@3x.png
new file mode 100644 (file)
index 0000000..33f3b2a
Binary files /dev/null and "b/LingQi/LingQi/Assets.xcassets/mine/mine_cell_service.imageset/\350\275\254\350\264\246@3x.png" differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_msg.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/mine_msg.imageset/Contents.json
new file mode 100644 (file)
index 0000000..6866d51
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_msg.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_msg.imageset/ic_msg.png b/LingQi/LingQi/Assets.xcassets/mine/mine_msg.imageset/ic_msg.png
new file mode 100644 (file)
index 0000000..9e1680b
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/mine_msg.imageset/ic_msg.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_set.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/mine_set.imageset/Contents.json
new file mode 100644 (file)
index 0000000..35d6ec5
--- /dev/null
@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "filename" : "ic_set.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/mine_set.imageset/ic_set.png b/LingQi/LingQi/Assets.xcassets/mine/mine_set.imageset/ic_set.png
new file mode 100644 (file)
index 0000000..6e75d39
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/mine_set.imageset/ic_set.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/select_normal.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/select_normal.imageset/Contents.json
new file mode 100644 (file)
index 0000000..4b7bf60
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Frame.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Frame@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Frame@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/select_normal.imageset/Frame.png b/LingQi/LingQi/Assets.xcassets/mine/select_normal.imageset/Frame.png
new file mode 100644 (file)
index 0000000..b2c2400
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/select_normal.imageset/Frame.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/select_normal.imageset/Frame@2x.png b/LingQi/LingQi/Assets.xcassets/mine/select_normal.imageset/Frame@2x.png
new file mode 100644 (file)
index 0000000..b7cf13e
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/select_normal.imageset/Frame@2x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/select_normal.imageset/Frame@3x.png b/LingQi/LingQi/Assets.xcassets/mine/select_normal.imageset/Frame@3x.png
new file mode 100644 (file)
index 0000000..0f593d5
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/select_normal.imageset/Frame@3x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/select_selected.imageset/Contents.json b/LingQi/LingQi/Assets.xcassets/mine/select_selected.imageset/Contents.json
new file mode 100644 (file)
index 0000000..e30ad51
--- /dev/null
@@ -0,0 +1,23 @@
+{
+  "images" : [
+    {
+      "filename" : "Group 334.png",
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "Group 334@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "Group 334@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/LingQi/LingQi/Assets.xcassets/mine/select_selected.imageset/Group 334.png b/LingQi/LingQi/Assets.xcassets/mine/select_selected.imageset/Group 334.png
new file mode 100644 (file)
index 0000000..68db34e
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/select_selected.imageset/Group 334.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/select_selected.imageset/Group 334@2x.png b/LingQi/LingQi/Assets.xcassets/mine/select_selected.imageset/Group 334@2x.png
new file mode 100644 (file)
index 0000000..ec52a67
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/select_selected.imageset/Group 334@2x.png differ
diff --git a/LingQi/LingQi/Assets.xcassets/mine/select_selected.imageset/Group 334@3x.png b/LingQi/LingQi/Assets.xcassets/mine/select_selected.imageset/Group 334@3x.png
new file mode 100644 (file)
index 0000000..05c0fb7
Binary files /dev/null and b/LingQi/LingQi/Assets.xcassets/mine/select_selected.imageset/Group 334@3x.png differ
diff --git a/LingQi/LingQi/Base.lproj/LaunchScreen.storyboard b/LingQi/LingQi/Base.lproj/LaunchScreen.storyboard
new file mode 100644 (file)
index 0000000..865e932
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+</document>
diff --git a/LingQi/LingQi/Base.lproj/Main.storyboard b/LingQi/LingQi/Base.lproj/Main.storyboard
new file mode 100644 (file)
index 0000000..25a7638
--- /dev/null
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="tne-QT-ifu">
+            <objects>
+                <viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
+                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
+            </objects>
+        </scene>
+    </scenes>
+</document>
diff --git a/LingQi/LingQi/Ble/BlueToothManager.swift b/LingQi/LingQi/Ble/BlueToothManager.swift
new file mode 100644 (file)
index 0000000..d99bd5f
--- /dev/null
@@ -0,0 +1,164 @@
+//
+//  BlueToothManager.swift
+//  BlueToothDemo
+//
+//  Created by lianzi on 2022/10/9.
+//
+
+import CoreBluetooth
+
+class BlueToothManager:NSObject{
+    /// 状态改变
+    var didUpdateStateBlock:((_ central: CBCentralManager) ->Void)?
+    
+    /// 扫描到设备
+    var discoverDeviceBlock:((CBPeripheral,[String : Any],NSNumber) ->Void)?
+    /// 连接设备成功
+    var didConnectBlock:((CBPeripheral) ->Void)?
+    /// 连接设备失败
+    var FailConnectBlock:((CBPeripheral) ->Void)?
+    /// 设备断开连接
+    var disConnectBlock:((CBPeripheral) ->Void)?
+    
+    /// 发现服务
+    var discoverServiceBlock:(([CBService]) ->Void)?
+    /// 发现特征
+    var discoverPeripheralBlock:(([CBCharacteristic]) ->Void)?
+    
+    /// 读取到数据
+    var receiveDataBlock:((CBPeripheral,CBCharacteristic) ->Void)?
+    /// 写入数据(发送指令)成功
+    var didWriteDataBlock:((CBPeripheral,CBCharacteristic,Error?) ->Void)?
+    /// 读取信息成功
+    var didReadRSSIBlock:((CBPeripheral,NSNumber) ->Void)?
+    
+    
+    ///  中央管理类,管理蓝牙的扫描连接
+    lazy var centralManager :CBCentralManager = {
+        let manager = CBCentralManager(delegate: self, queue: nil)
+        return manager
+    }()
+    
+    override init() {
+        super.init()
+        _ = centralManager.isScanning
+    }
+
+    /// 开始扫描
+    func startScan(){
+        // withServices nil代表可以扫描任何的设备
+        //CBCentralManagerScanOptionAllowDuplicatesKey是允许重复扫描到
+        centralManager.scanForPeripherals(withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicatesKey:true])
+    }
+    
+    /// 停止扫描
+    func stopScan(){
+        centralManager.stopScan()
+    }
+    
+    /// 连接外设
+    /// - Parameter peripheral: 外设
+    func connect(peripheral:CBPeripheral){
+        centralManager.connect(peripheral)
+    }
+    
+    /// 取消连接外设
+    /// - Parameter peripheral: 外设
+    func cancelConnect(peripheral:CBPeripheral){
+        centralManager.cancelPeripheralConnection(peripheral)
+    }
+
+    /// 发送数据
+    /// - Parameters:
+    ///   - peripheral: 外设
+    ///   - characteristic: 特征
+    ///   - data: 数据
+    func sendTo(peripheral:CBPeripheral, characteristic:CBCharacteristic, data:Data){
+        peripheral.writeValue(data, for: characteristic, type: .withoutResponse)
+    }
+}
+
+extension BlueToothManager:CBCentralManagerDelegate{
+    /// 手机蓝牙状态更新
+    /// - Parameter central: 中央管理类
+    func centralManagerDidUpdateState(_ central: CBCentralManager) {
+        didUpdateStateBlock?(central)
+        switch central.state{
+            case .unknown:
+                print("unknown")
+            case .resetting:
+                print("resetting")
+            case .unsupported:
+                print("unsupported")
+            case .unauthorized:
+                print("unauthorized")
+            case .poweredOff:
+                print("poweredOff")
+            case .poweredOn:
+                print("poweredOn")
+                startScan()
+            @unknown default:
+                break
+        }
+    }
+    /// 发现设备
+    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
+        discoverDeviceBlock?(peripheral,advertisementData,RSSI)
+    }
+    
+    /// 连接上设备
+    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
+        peripheral.delegate = self
+        peripheral.discoverServices(nil)
+        didConnectBlock?(peripheral)
+    }
+    /// 连接失败
+    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
+        FailConnectBlock?(peripheral)
+    }
+    /// 断开连接
+    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
+        disConnectBlock?(peripheral)
+    }
+}
+
+extension BlueToothManager:CBPeripheralDelegate{
+    /// 读取到信号
+    func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: Error?) {
+        didReadRSSIBlock?(peripheral,RSSI)
+    }
+    /// 发现服务
+    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
+        if error == nil,let list = peripheral.services {
+            for s in list {
+                peripheral.discoverCharacteristics(nil, for: s)
+            }
+            discoverServiceBlock?(list)
+        }
+        else{
+            peripheral.discoverServices(nil)
+        }
+    }
+    /// 发现服务找那个的特征,然后遍历所有特征订阅
+    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
+        if error == nil,let list = service.characteristics {
+//            for s in list {
+//                peripheral.setNotifyValue(true, for: s)
+//            }
+            discoverPeripheralBlock?(list)
+        }
+    }
+    /// 特征状态发生变化通知
+    func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
+        //读取特征的值
+        peripheral.readValue(for: characteristic)
+    }
+    /// 特征发生变化
+    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
+        receiveDataBlock?(peripheral,characteristic)
+    }
+    /// 写入完成(发送指令完成)
+    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
+        didWriteDataBlock?(peripheral,characteristic,error)
+    }
+}
diff --git a/LingQi/LingQi/Ble/BlueToothViewModel.swift b/LingQi/LingQi/Ble/BlueToothViewModel.swift
new file mode 100644 (file)
index 0000000..01eec82
--- /dev/null
@@ -0,0 +1,166 @@
+//
+//  BlueToothViewModel.swift
+//  BlueToothDemo
+//
+//  Created by lianzi on 2022/10/9.
+//
+
+import CoreBluetooth
+import UIKit
+
+class BlueToothViewModel:NSObject{
+    static let shareModel = BlueToothViewModel()
+    
+    let bluetooth =  BlueToothManager()//蓝牙管理类
+    var deviceList = [ScanModel]()//设备列表
+    
+    var selectedPeripheral:CBPeripheral?//连接上的设备
+    var readCha:CBCharacteristic?//读特征
+    var writeCha:CBCharacteristic?//写特征
+    
+    
+    var deviceListDidChange:(()->Void)?//扫描列表设备改变
+    
+    override init() {
+        super.init()
+        setupBluetooth()
+        setupData()
+    }
+    
+}
+
+extension BlueToothViewModel{
+
+    func setupData(){
+    }
+    func reset(){
+        deviceList = [ScanModel]()//设备列表
+        selectedPeripheral = nil
+    }
+}
+
+extension BlueToothViewModel{
+    func setupBluetooth(){
+        //状态改变
+        bluetooth.didUpdateStateBlock = {[weak self](centrl) in
+            self?.didUpdateStats(centrl.state)
+        }
+        // 扫描到设备
+        bluetooth.discoverDeviceBlock = discoverDevice(peripheral:data:rssi:)
+        // 连接设备成功
+        bluetooth.didConnectBlock = {[weak self] (device) in
+            LogManager.instance.add("已连接")
+            self?.selectedPeripheral = device
+//            self?.didConnect?(device)
+            
+        }
+        // 连接设备失败
+        bluetooth.FailConnectBlock = { (device) in
+            LogManager.instance.add("连接失败")
+        }
+        // 设备断开连接
+        bluetooth.disConnectBlock = {[weak self](device) in
+            LogManager.instance.add("断开连接")
+//            SVProgressHUD.showAutoHiden("disconnect")
+//            self?.retryConnect()
+        }
+        // 发现服务
+        bluetooth.discoverServiceBlock = { (services) in
+            LogManager.instance.add("发现服务 \(services)")
+        }
+        // 发现特征
+        bluetooth.discoverPeripheralBlock = {[weak self] (characteristics) in
+            guard let self = self else {return}
+            LogManager.instance.add("发现特征 \(characteristics)")
+            for cha in characteristics{
+                if cha.uuid.uuidString == "FED7" {
+                    self.writeCha = cha
+                    self.sendGetDetail()
+                }
+                if cha.uuid.uuidString == "FED8" {
+                    self.readCha = cha
+                    self.selectedPeripheral?.setNotifyValue(true, for: cha)
+                }
+            }
+        }
+        // 读取到数据
+        bluetooth.receiveDataBlock = {[weak self] (peripheral,characteristic) in
+//            print("接收到数据",characteristic)
+//            print(characteristic.uuid.uuidString," === ",characteristic.value ?? "")
+            if let data = characteristic.value{
+                self?.receiveData(data)
+            }
+        }
+        // 写入数据(发送指令)成功
+        bluetooth.didWriteDataBlock = { (peripheral,characteristic,error) in
+            LogManager.instance.add("发送指令,错误 = \(error)");
+        }
+    }
+    func discoverDevice(peripheral:CBPeripheral, data:[String : Any],rssi: NSNumber){
+        guard let name = peripheral.name else{
+            return
+        }
+        if name.isEmpty {
+            return
+        }
+//        if !name.hasPrefix("BlueNRG") {
+//            return
+//        }
+        
+        var isContain = false
+        for device in deviceList{
+            if device.peripheral.identifier.uuidString == peripheral.identifier.uuidString {
+//                print("peripheral 的uuid===",device.peripheral.identifier.uuidString)
+                isContain = true
+                break
+            }
+        }
+        if !isContain{
+            let model = ScanModel()
+            model.peripheral = peripheral
+            model.rssi = rssi
+            deviceList.append(model)
+            deviceListDidChange?()
+            print(name,data)
+        }
+    }
+    func didUpdateStats(_ states:CBManagerState){
+        switch states{
+            case .poweredOn:
+            LogManager.instance.add("poweredOn")
+            @unknown default:
+                break
+        }
+    }
+}
+
+extension BlueToothViewModel{
+    func sendGetDetail(){
+        let data = SendManager.getDetail()
+        sendToDevice(data)
+    }
+    func sendStopDetail(){
+        let data = SendManager.getDetail()
+        sendToDevice(data)
+    }
+    
+    func sendToDevice(_ data:Data){
+        LogManager.instance.add("[send] = \(data.hexEncodedString())")
+        guard let p = selectedPeripheral,let c = writeCha else{
+            LogManager.instance.add("请先连接设备!!! ")
+            return
+        }
+        bluetooth.sendTo(peripheral:p , characteristic: c, data: data)
+    }
+}
+
+extension BlueToothViewModel{
+    func receiveData(_ data:Data){
+        LogManager.instance.add("[recevice] = \(data.hexEncodedString())")
+
+    }
+
+}
+
+
+
diff --git a/LingQi/LingQi/Ble/ReceiveManager.swift b/LingQi/LingQi/Ble/ReceiveManager.swift
new file mode 100644 (file)
index 0000000..f573650
--- /dev/null
@@ -0,0 +1,8 @@
+//
+//  ReceiveManager.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/3.
+//
+
+import Foundation
diff --git a/LingQi/LingQi/Ble/ScanModel.swift b/LingQi/LingQi/Ble/ScanModel.swift
new file mode 100644 (file)
index 0000000..d34d678
--- /dev/null
@@ -0,0 +1,14 @@
+//
+//  ScanModel.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/3.
+//
+
+import Foundation
+import CoreBluetooth
+/// 扫描的model
+class ScanModel{
+    var peripheral:CBPeripheral!
+    var rssi:NSNumber!
+}
diff --git a/LingQi/LingQi/Ble/SendManager.swift b/LingQi/LingQi/Ble/SendManager.swift
new file mode 100644 (file)
index 0000000..f5635d1
--- /dev/null
@@ -0,0 +1,75 @@
+//
+//  SendManager.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/3.
+//
+
+import Foundation
+class SendManager {
+    static func getDetail() ->Data{
+        var bytes = [UInt8](repeating: 0x00, count: 8)
+        bytes[0] = 0xFD
+        bytes[1] = 0x35
+        bytes[2] = 0x09
+        bytes[3] = 0x00
+        bytes[4] = 0x00
+        bytes[5] = 0x00
+        bytes[6] = 0x00
+        bytes[7] = 0x00
+        let data = SendManager.byteToData(arr: bytes)
+        return data
+    }
+    static func stopDetail() ->Data{
+        var bytes = [UInt8](repeating: 0x00, count: 4)
+        bytes[0] = 0xFD
+        bytes[1] = 0x36
+        bytes[2] = 0x05
+        bytes[3] = 0x00
+        let data = SendManager.byteToData(arr: bytes)
+        return data
+    }
+}
+
+extension SendManager{
+    public static func byteToData(arr:[UInt8]) -> Data{
+        let bytes = SendManager.appendXmodem(arr: arr)
+        let data = Data(bytes: bytes, count: bytes.count)
+        return data
+    }
+    
+    public static func appendXmodem(arr:[UInt8]) -> [UInt8]{
+        var crc = CRC16.xmodem(arr: arr)
+        var list:[UInt8] = [UInt8](repeating: 0x00, count: arr.count + 2)
+        for i in 0..<arr.count{
+            list[i] = arr[i]
+        }
+        
+        let crcData: Data = Data(bytes: &crc, count: 2)
+        let crcBytes = [UInt8](crcData)
+        list[arr.count] = crcBytes[1]
+        list[arr.count + 1] = crcBytes[0]
+        
+        return list
+    }
+}
+class CRC16{
+    public static func xmodem(arr: [UInt8]) -> Int {
+        var wCRCin = 0x0000;
+        let wCPoly = 0x1021;
+        let len = arr.count;
+        for i in 0...len-1 {
+            for j in 0...7 {
+                let bit = ((arr[i] >> (7 - j) & 1) == 1);
+                let c15 = ((wCRCin >> 15 & 1) == 1);
+                wCRCin <<= 1;
+                if(c15 != bit) {
+                    wCRCin ^= wCPoly;
+                }
+            }
+        }
+        wCRCin &= 0xFFFF;
+        wCRCin ^= 0x0000;
+        return wCRCin
+    }
+}
diff --git a/LingQi/LingQi/Info.plist b/LingQi/LingQi/Info.plist
new file mode 100644 (file)
index 0000000..f88d044
--- /dev/null
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+       <key>UIApplicationSceneManifest</key>
+       <dict>
+               <key>UIApplicationSupportsMultipleScenes</key>
+               <false/>
+               <key>UISceneConfigurations</key>
+               <dict>
+                       <key>UIWindowSceneSessionRoleApplication</key>
+                       <array>
+                               <dict>
+                                       <key>UISceneConfigurationName</key>
+                                       <string>Default Configuration</string>
+                                       <key>UISceneDelegateClassName</key>
+                                       <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
+                                       <key>UISceneStoryboardFile</key>
+                                       <string>Main</string>
+                               </dict>
+                       </array>
+               </dict>
+       </dict>
+       <key>NSPhotoLibraryUsageDescription</key>
+       <string>修改用户头像、提交意见反馈需要访问相册</string>
+       <key>NSCameraUsageDescription</key>
+       <string>修改用户头像、提交意见反馈需要访问相册使用摄像头</string>
+</dict>
+</plist>
diff --git a/LingQi/LingQi/LingQi-Bridging-Header.h b/LingQi/LingQi/LingQi-Bridging-Header.h
new file mode 100644 (file)
index 0000000..58d97ae
--- /dev/null
@@ -0,0 +1,9 @@
+//
+//  Magpie-Bridging-Header.h
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+//#import "SVProgressHUD+YLAdd.h"
+#import "YLTimerButton.h"
diff --git a/LingQi/LingQi/MixApi/MixApi.swift b/LingQi/LingQi/MixApi/MixApi.swift
new file mode 100644 (file)
index 0000000..177778b
--- /dev/null
@@ -0,0 +1,69 @@
+//
+//  MixApi.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/6.
+//
+
+import Foundation
+import CoreBluetooth
+
+public class MixDevice{
+    
+    /// 设备
+     var peripheral: CBPeripheral!
+    
+    /// 广播信息
+     var advertisementData: [String : AnyObject]?
+    
+    /// 信号
+     var RSSI: Int32?
+}
+
+public protocol MixApi  {
+    
+    /// 单利
+    static var manager: MixApi { get }
+    
+    /// 发现设备
+    var discoverDevice:((_ devices:[MixDevice]) -> Void)? { get }
+    
+    /// 收到sdk传数过来的数据,具体请阅读每条指令参数说明
+    var receiveData:((_ data:Any) -> Void)? { get  }
+    
+    /// 扫描
+    /// - Parameters:
+    ///   - uuid: 指定设备
+    ///   - duration: 超时
+    func scanWithServices(_ uuid: [String]?, duration: TimeInterval)
+    
+    /// 停止扫描
+    func stopScan()
+    
+    /// 连接设备
+    /// - Parameters:
+    ///   - device: 扫描到的涉笔
+    ///   - duration: 超时时间
+    ///   - success: 连接成功
+    ///   - fail: 连接失败
+    func connect(device : MixDevice, duration: TimeInterval, success: @escaping (() -> Void), fail: @escaping ((_ error:[String:Any]) -> Void))
+    
+    /// 连接设备
+    /// - Parameters:
+    ///   - identifier: 设备标识符
+    ///   - duration: 超时时间
+    ///   - success: 连接成功
+    ///   - fail: 连接失败
+    func connect(identifier : String, duration: TimeInterval, success: @escaping (() -> Void), fail: @escaping ((_ error:[String:Any]) -> Void))
+    
+    
+    /// 取消当前连接
+    func cancelConnect()
+    
+    /// 发送指令
+    /// - Parameters:
+    ///   - parameters: 无参传nil,具体key-value请阅读每条指令参数说明
+    ///   - success: 发送成功
+    ///   - failure: 发送失败
+    func sendCommand(parameters: [String : Any]?, success:@escaping (() -> Void), failure:@escaping ((_ error:[String:Any]) -> Void))
+}
diff --git a/LingQi/LingQi/Resource/colors/Colors+YL.swift b/LingQi/LingQi/Resource/colors/Colors+YL.swift
new file mode 100644 (file)
index 0000000..0c12722
--- /dev/null
@@ -0,0 +1,51 @@
+//
+//  Colors+YL.swift
+//  zgjd
+//
+//  Created by apple on 2020/11/12.
+//
+
+import UIKit
+
+public enum YLColor {
+    ///
+    case bgColor
+    ///  主题色
+    case theme
+    ///  次级主题色
+    case subTheme
+    ///  主标题 - 0x222222
+    case first
+    ///  主标题 - 0x333333
+    case primary
+    ///  二级标题 - 0x666666
+    case secondary
+    ///  三级标题 - 0x999999
+    case tertiary
+
+    case separateLine
+}
+
+extension YLColor: ColorRGBProviderProtocol {
+    public var rgbValue: Int {
+        switch self {
+        case .bgColor:
+            return 0x11131E
+        case .theme:
+            return 0x286DE8
+        case .subTheme:
+            return 0xF4FAFF
+        case .first:
+            return 0x222222
+        case .primary:
+            return 0x333333
+        case .secondary:
+            return 0x666666
+        case .tertiary:
+            return 0x999999
+        case .separateLine:
+            return 0xffffff
+        }
+    }
+}
+
diff --git a/LingQi/LingQi/Resource/colors/Colors.swift b/LingQi/LingQi/Resource/colors/Colors.swift
new file mode 100644 (file)
index 0000000..b5d5018
--- /dev/null
@@ -0,0 +1,43 @@
+//
+//  Colors.swift
+//  zgjd
+//
+//  Created by apple on 2020/11/9.
+//
+
+import UIKit
+
+public extension UIColor {
+    static func color(_ color: YLColor, _ alpha: CGFloat = 1) -> UIColor {
+        return UIColor.rgb(color.rgbValue, alpha)
+    }
+}
+
+public protocol ColorRGBProviderProtocol {
+    var rgbValue: Int { get }
+}
+
+public func kColor(_ RGB: Int, _ alpha: CGFloat = 1) -> UIColor {
+    return UIColor.rgb(RGB, alpha)
+}
+
+public extension UIColor {
+    static func rgb(_ RGB: Int, _ alpha: CGFloat = 1) -> UIColor {
+        assert(0...0xFFFFFF ~= RGB, "The color hex value must between 0 to 0xFFFFFF.")
+        
+        let red = Float(((RGB & 0xFF0000) >> 16)) / 255.0
+        let green = Float(((RGB & 0x00FF00) >> 8)) / 255.0
+        let blue = Float(RGB & 0x0000FF) / 255.0
+        return UIColor.init(red: CGFloat(red), green: CGFloat(green), blue: CGFloat(blue), alpha: alpha)
+    }
+    
+    var half: UIColor {
+        var red: CGFloat = 0
+        var green: CGFloat = 0
+        var blue: CGFloat = 0
+        var alpha: CGFloat = 0
+        getRed(&red, green: &green, blue: &blue, alpha: &alpha)
+        return UIColor(red: red, green: green, blue: blue, alpha: alpha * 0.5)
+    }
+}
+
diff --git a/LingQi/LingQi/Resource/fonts/UIFont+ZKYS.swift b/LingQi/LingQi/Resource/fonts/UIFont+ZKYS.swift
new file mode 100644 (file)
index 0000000..7374edd
--- /dev/null
@@ -0,0 +1,43 @@
+//
+//  UIFont+ZKYS.swift
+//  zgjd
+//
+//  Created by apple on 2020/11/9.
+//
+
+import UIKit
+
+// MARK: - ****** 字体相关 ******
+/*
+ ======  FamilyName : PingFang SC ======
+ === 1.  PingFangSC-Medium
+ === 2.  PingFangSC-Semibold
+ === 3.  PingFangSC-Light
+ === 4.  PingFangSC-Ultralight
+ === 5.  PingFangSC-Regular
+ === 6.  PingFangSC-Thin
+ */
+public extension UIFont {
+    
+    static func light(_ size: CGFloat, isFit: Bool = true) -> UIFont {
+        return UIFont.systemFont(ofSize: size.fit(isFit), weight: .light)
+    }
+    static func regular(_ size: CGFloat, isFit: Bool = true) -> UIFont {
+        return UIFont.systemFont(ofSize: size.fit(isFit), weight: .regular)
+    }
+    static func medium(_ size: CGFloat, isFit: Bool = true) -> UIFont {
+        return UIFont.systemFont(ofSize: size.fit(isFit), weight: .medium)
+    }
+    static func semiBold(_ size: CGFloat, isFit: Bool = true) -> UIFont {
+        return UIFont.systemFont(ofSize: size.fit(isFit), weight: .semibold)
+    }
+    static func bold(_ size: CGFloat, isFit: Bool = true) -> UIFont {
+        return UIFont.systemFont(ofSize: size.fit(isFit), weight: .bold)
+    }
+}
+
+extension CGFloat {
+    fileprivate func fit(_ isFit: Bool) -> CGFloat {
+        return isFit ? self.fitR : self
+    }
+}
diff --git a/LingQi/LingQi/SceneDelegate.swift b/LingQi/LingQi/SceneDelegate.swift
new file mode 100644 (file)
index 0000000..c25595f
--- /dev/null
@@ -0,0 +1,89 @@
+//
+//  SceneDelegate.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/29.
+//
+
+import UIKit
+import IQKeyboardManagerSwift
+class SceneDelegate: UIResponder, UIWindowSceneDelegate {
+    
+    var window: UIWindow?
+
+
+    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
+        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
+        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
+        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
+        guard let _ = (scene as? UIWindowScene) else { return }
+        
+        App.shared.window = window
+        setConfig()
+
+//        window?.rootViewController = LoginVC()
+        window?.rootViewController = BaseTC()
+        
+    }
+
+    func sceneDidDisconnect(_ scene: UIScene) {
+        // Called as the scene is being released by the system.
+        // This occurs shortly after the scene enters the background, or when its session is discarded.
+        // Release any resources associated with this scene that can be re-created the next time the scene connects.
+        // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
+    }
+
+    func sceneDidBecomeActive(_ scene: UIScene) {
+        // Called when the scene has moved from an inactive state to an active state.
+        // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
+    }
+
+    func sceneWillResignActive(_ scene: UIScene) {
+        // Called when the scene will move from an active state to an inactive state.
+        // This may occur due to temporary interruptions (ex. an incoming phone call).
+    }
+
+    func sceneWillEnterForeground(_ scene: UIScene) {
+        // Called as the scene transitions from the background to the foreground.
+        // Use this method to undo the changes made on entering the background.
+    }
+
+    func sceneDidEnterBackground(_ scene: UIScene) {
+        // Called as the scene transitions from the foreground to the background.
+        // Use this method to save data, release shared resources, and store enough scene-specific state information
+        // to restore the scene back to its current state.
+    }
+
+    func setConfig(){
+        if #available(iOS 15.0, *) {
+            UITableView.appearance().sectionHeaderTopPadding = 0
+        }
+        IQKeyboardManager.shared.enableAutoToolbar = true
+        IQKeyboardManager.shared.isEnabled = true
+        IQKeyboardManager.shared.resignOnTouchOutside = true
+    }
+}
+
+class App{
+    static let shared = App()
+     var window:UIWindow?
+     func topVC()->UIViewController!{
+         guard let vc = window?.rootViewController else{
+             print("页面异常!!!")
+             return UIViewController()
+         }
+         return getTopViewController(from: vc)
+    }
+    
+    private func getTopViewController(from vc: UIViewController) -> UIViewController {
+        if let navVC = vc as? UINavigationController {
+            return getTopViewController(from: navVC.visibleViewController ?? navVC)
+        } else if let tabVC = vc as? UITabBarController {
+            return getTopViewController(from: tabVC.selectedViewController ?? tabVC)
+        } else if let presentedVC = vc.presentedViewController {
+            return getTopViewController(from: presentedVC)
+        } else {
+            return vc
+        }
+    }
+}
diff --git a/LingQi/LingQi/Tools/BaseSizeMacro.swift b/LingQi/LingQi/Tools/BaseSizeMacro.swift
new file mode 100644 (file)
index 0000000..f64dd2a
--- /dev/null
@@ -0,0 +1,146 @@
+//
+//  BaseSizeMacro.swift
+//  zgjd
+//
+//  Created by apple on 2020/11/9.
+//
+
+import UIKit
+
+// MARK: - ********* Device Size
+public var kScreenWid: CGFloat { return UIScreen.main.bounds.size.width }
+
+public var kScreenHei: CGFloat { return UIScreen.main.bounds.size.height }
+
+public var kIsX: Bool { return ScreenSize.shared.isIphonex }
+
+public var kNavBtm: CGFloat { return kNavTop + 44 }
+public var kCusNavBtm: CGFloat {
+    if kIsX {
+        return 88.fitR
+    }
+    return 64.fitR
+}
+public var kNavTop: CGFloat {
+    if kIsX { return 44 }
+    return 20
+}
+
+
+public var kHairHei: CGFloat {
+    if kIsX { return 30 }
+    return 0
+}
+
+public var kSafeBtm: CGFloat {
+    if kIsX { return 34 }
+    return 0
+}
+
+public var kSafeBottom: CGFloat {
+    if kIsX { return 20 }
+    return 0
+}
+
+public var kTabbarHei: CGFloat {
+    if kIsX { return 34 + 49 }
+    return 49
+}
+
+
+// MARK: - ********* Public Quick Funcs
+let kPageSize = "10"
+
+typealias VoidClosure = (() -> Void)
+///  printf
+public func k_log<T>(_ item: T,
+                        file: String = #file,
+                        line: Int = #line,
+                        function: String = #function) {
+    #if DEBUG
+    print("================== debug log ==================")
+    print("time: \(currentTime)")
+    print("file: \((file as NSString).lastPathComponent) \t line: \(line) \t func: \(function)")
+    print("log:  \(item)\n")
+    #endif
+}
+
+fileprivate var currentTime: String {
+    let timeStr = "\(Date().addingTimeInterval(8 * 60 * 60))"
+    return String(timeStr.prefix(20))
+}
+
+public func k_logViewControllerDeinit(_ vc: UIViewController) {
+    #if DEBUG
+    guard let viewDesc = "\(vc.self)".split(separator: ".").last
+    else { return }
+    print("Deinit:  --->  ViewController:\t\(String(viewDesc))")
+    #endif
+}
+
+public func k_logViewDeinit(_ view: UIView) {
+    #if DEBUG
+    guard let desc = "\(view.self)".split(separator: ";").first,
+         let viewDesc = String(desc).split(separator: ".").last
+        else { return }
+    print("Deinit:  --->  View:\t\t\t\(String(viewDesc))")
+    #endif
+}
+
+public func k_logViewModelDeinit(_ vm: AnyObject) {
+    #if DEBUG
+    guard let vmDesc = "\(vm.self)".split(separator: ".").last
+    else { return }
+    print("Deinit:  --->  ViewModel:\t\t\(String(vmDesc))")
+    #endif
+}
+
+///  获取对象的地址
+public func kObjectAddress(_ obj: NSObject) -> String {
+    return String.init(format: "%p", obj)
+}
+
+///  主线程 延时
+public func kDelay(_ delay: Double, onQueue queue: DispatchQueue = DispatchQueue.main,  closure: @escaping () -> Void) {
+    queue.asyncAfter(deadline: .now() + delay, execute: closure)
+}
+
+public extension DispatchQueue {
+    // This method will dispatch the `block` to self.
+    // If `self` is the main queue, and current thread is main thread, the block
+    // will be invoked immediately instead of being dispatched.
+    func safeAsync(_ block: @escaping () -> Void) {
+        if self === DispatchQueue.main && Thread.isMainThread {
+            block()
+        } else {
+            async { block() }
+        }
+    }
+}
+
+//final class ScreenSize {
+//    
+//    static let shared = ScreenSize()
+//    init() {
+//        p_refreshData()
+//    }
+//    
+//    private(set) var screenWidthRatio: CGFloat = 1
+//    private(set) var screenHeightRatio: CGFloat = 1
+//    private(set) var isIphonex = false
+//    
+//    //  默认参考 size = (375,667)
+//    private let designSize = CGSize.init(width: 375, height: 667)
+//    private func p_refreshData() {
+//        let screenWidth = UIScreen.main.bounds.size.width
+//        let screenHeight = UIScreen.main.bounds.size.height
+//        screenWidthRatio = screenWidth / designSize.width
+//        screenHeightRatio = screenHeight / designSize.height
+//                
+//        if #available(iOS 11.0, *),
+//           UIApplication.shared.delegate?
+//                .window??.safeAreaInsets.bottom != 0 {
+//            isIphonex = true
+//        }
+//    }
+//}
diff --git a/LingQi/LingQi/Tools/Category/Data+YL.swift b/LingQi/LingQi/Tools/Category/Data+YL.swift
new file mode 100644 (file)
index 0000000..e4a5145
--- /dev/null
@@ -0,0 +1,33 @@
+//
+//  Data+YL.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/3.
+//
+
+import Foundation
+extension Data {
+    struct HexEncodingOptions: OptionSet {
+        let rawValue: Int
+        static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
+    }
+
+    func hexEncodedString(options: HexEncodingOptions = []) -> String {
+        let format = options.contains(.upperCase) ?"%02hhX" :"%02hhx"
+        return map { String(format: format, $0) }.joined()
+    }
+    func toString()->String{
+        return String(data: self, encoding: .ascii) ?? ""
+    }
+    
+    func toInt()->Int{
+        var receive1: Int = 0
+        (self as NSData).getBytes(&receive1, length: 8)
+        return receive1
+    }
+    func toInt16()->Int16{
+        var receive1: Int16 = 0
+        (self as NSData).getBytes(&receive1, length: 16)
+        return receive1
+    }
+}
diff --git a/LingQi/LingQi/Tools/Category/Open+map.swift b/LingQi/LingQi/Tools/Category/Open+map.swift
new file mode 100644 (file)
index 0000000..6f785d4
--- /dev/null
@@ -0,0 +1,102 @@
+//
+//  Open+map.swift
+//  zgjd
+//
+//  Created by apple on 2020/12/16.
+//
+
+import Foundation
+import MapKit
+
+struct MapTool {
+    /// Info plist
+    /// LSApplicationQueriesSchemes 需要添加 iosamap
+    private static let aMapScheme = "iosamap://"
+    private static let aMapSchemeUrl = URL(string: aMapScheme)
+    private static var canOpenAmap: Bool {
+        if let url = aMapSchemeUrl {
+            return UIApplication.shared.canOpenURL(url)
+        } else {
+            return false
+        }
+    }
+    
+    private static let mapsScheme = "http://maps.apple.com/"
+    private static let mapsSchemeUrl = URL(string: mapsScheme)
+    private static var canOpenMaps: Bool {
+        if let url = mapsSchemeUrl {
+            return UIApplication.shared.canOpenURL(url)
+        } else {
+            return false
+        }
+    }
+    
+    /// Info plist
+    /// LSApplicationQueriesSchemes 需要添加 baidumap
+    private static let bMapScheme = "baidumap://"
+    private static let bMapSchemeUrl = URL(string: bMapScheme)
+    private static var canOpenbMap: Bool {
+        if let url = bMapSchemeUrl {
+            return UIApplication.shared.canOpenURL(url)
+        } else {
+            return false
+        }
+    }
+    
+    /// 导航功能方法封装
+    /// @param lat 纬度
+    /// @param lng 经度
+    /// @param address 地图显示目的地
+    /// @param currentController 在哪个VC弹出
+//    static func mapNavigation(lat: Double, lng: Double, address: String, currentVC: UIViewController) {
+//        let urlScheme = ""
+//        let appName = ""
+//        var address = address
+//        let coordiante = CLLocationCoordinate2DMake(lat, lng)
+//        if address.isEmpty {
+//            address = "目的地"
+//        }
+//        let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
+//        if canOpenMaps {
+//            let action = UIAlertAction(title: "苹果地图", style: .default) { (action) in
+//                let currentLocation = MKMapItem.forCurrentLocation()
+//                let toLocation = MKMapItem(placemark: MKPlacemark(coordinate: coordiante))
+//                toLocation.name = address
+//                MKMapItem.openMaps(with: [currentLocation, toLocation],
+//                                   launchOptions: [
+//                                    MKLaunchOptionsDirectionsModeKey:MKLaunchOptionsDirectionsModeDriving,
+//                                    MKLaunchOptionsShowsTrafficKey:true]
+//                )
+//            }
+//            alert.addAction(action)
+//        }
+//        if canOpenbMap {
+//            let action = UIAlertAction(title: "百度地图", style: .default) { (action) in
+//                let bstr = "baidumap://map/direction?origin={{我的位置}}&destination=name:\(address)|latlng:\(coordiante.latitude),\(coordiante.longitude)&mode=driving&coord_type=gcj02"
+//                let urlStr = bstr.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
+//                guard let urlStr2 = urlStr else { return }
+//                guard let url = urlStr2.url else { return }
+//                UIApplication.shared.open(url, options: [:]) { (success) in
+//                    SNLog("scheme try end")
+//                }
+//            }
+//            alert.addAction(action)
+//        }
+//        if canOpenAmap {
+//            let action = UIAlertAction(title: "高德地图", style: .default) { (action) in
+//                let bstr = "iosamap://path?sourceApplication=\(appName)&backScheme=\(urlScheme)&dlat=\(coordiante.latitude)&dlon=\(coordiante.longitude)&dname=\(address)&dev=0&t=0"
+//                let urlStr = bstr.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
+//                guard let urlStr2 = urlStr else { return }
+//                guard let url = urlStr2.url else { return }
+//                UIApplication.shared.open(url, options: [:]) { (success) in
+//                    SNLog("scheme try end")
+//                }
+//            }
+//            alert.addAction(action)
+//        }
+//        let action = UIAlertAction(title: "取消", style: .cancel, handler: nil)
+//        alert.addAction(action)
+//        
+//        currentVC.present(alert, animated: true, completion: nil)
+//    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/Array+Develop.swift b/LingQi/LingQi/Tools/Extensions/Array+Develop.swift
new file mode 100644 (file)
index 0000000..b634d70
--- /dev/null
@@ -0,0 +1,28 @@
+//
+//  Array+HTDevelop.swift
+//  HTDevelopTools
+//
+//  Created by 李扬 on 2019/3/8.
+//  Copyright © 2019 Exaleap. All rights reserved.
+//
+
+import UIKit
+
+public extension Array {
+    ///  是否是最后一个index
+    func isLastIndex(_ index: Int) -> Bool {
+        return index == (self.count - 1)
+    }
+    func toJSONString() -> String {
+         
+        if (!JSONSerialization.isValidJSONObject(self)) {
+            print("无法解析出JSONString")
+            return ""
+        }
+         
+        let data = try? JSONSerialization.data(withJSONObject: self, options: []) as NSData
+        let JSONString = NSString(data:data! as Data,encoding: String.Encoding.utf8.rawValue)
+        return JSONString! as String
+         
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/Array+Spec.swift b/LingQi/LingQi/Tools/Extensions/Array+Spec.swift
new file mode 100755 (executable)
index 0000000..d7bcc42
--- /dev/null
@@ -0,0 +1,46 @@
+//
+//  Array_Extension.swift
+//  ShenZhouDaDiXing
+//
+//  Created by spectator Mr.Z on 2016/11/4.
+//  Copyright © 2016年 ZZC WORKSPACE. All rights reserved.
+//
+
+import UIKit
+
+extension Array where Element: Equatable {
+    
+    // Remove first collection element that is equal to the given `object`:
+    public mutating func remove(object: Element) {
+        self = self.filter { $0 != object }
+    }
+}
+
+extension Array where Element == String {
+    
+    /// 数组转字符串
+    ///
+    /// - Parameter char: 数组间隔符
+    /// - Returns: 得到的字符串
+    public func string(_ char: String) -> String {
+        return self.joined(separator: char)
+    }
+    
+    func convertToStr(By: String) -> String {
+       let result = self.joined(separator: ",")
+        return result
+    }
+}
+
+extension Array where Element: UIView {
+    var cornerRadius: CGFloat {
+        set {
+            for v in self {
+                v.n_cornerRadius = newValue
+            }
+        }
+        get {
+            0
+        }
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/CAGradientLayer+Develop.swift b/LingQi/LingQi/Tools/Extensions/CAGradientLayer+Develop.swift
new file mode 100644 (file)
index 0000000..cf4c826
--- /dev/null
@@ -0,0 +1,61 @@
+//
+//  CAGradientLayer+HTDevelop.swift
+//  rrlWallet
+//
+//  Created by Gordon on 2017/8/5.
+//  Copyright © 2017年 Gordon. All rights reserved.
+//
+
+import UIKit
+
+public enum LYGradientLayerDirectionOption {
+    case top2down
+    case left2right
+    case topLeft2downRight
+    case topRight2downLeft
+    case other
+}
+
+public extension YCDevelop where Base: CAGradientLayer {
+    
+    /// 快速创建一个渐变的layer
+    ///
+    /// - Parameter colors: 渐变颜色
+    /// - Parameter frame: 渐变范围
+    /// - Parameter direction: 渐变方向
+    /// - Returns: gradientLayer
+    static func gradientLayerWith(colors: [UIColor], frame: CGRect, direction: LYGradientLayerDirectionOption) -> CAGradientLayer {
+        
+        let layer = CAGradientLayer()
+        layer.frame = frame
+        layer.colors = colors.map { return $0.cgColor }
+        var start = CGPoint(x: 0.5, y: 0)
+        var end = CGPoint(x: 0.5, y: 1)
+        switch direction {
+        case .top2down:
+            start = CGPoint(x: 0.5, y: 0)
+            end = CGPoint(x: 0.5, y: 1)
+        case .left2right:
+            start = CGPoint(x: 0, y: 0.5)
+            end = CGPoint(x: 1, y: 0.5)
+        case .topLeft2downRight:
+            start = CGPoint(x: 0, y: 0)
+            end = CGPoint(x: 1, y: 1)
+        case .topRight2downLeft:
+            start = CGPoint(x: 1, y: 0)
+            end = CGPoint(x: 0, y: 1)
+        case .other:
+            break
+        }
+        layer.startPoint = start
+        layer.endPoint = end
+        return layer
+    }
+}
+
+public extension YCDevelop where Base:UIView{
+    func addGardiendLayerWith(colors: [UIColor], frame: CGRect, direction: LYGradientLayerDirectionOption){
+        let gradientLayer = CAGradientLayer.yc.gradientLayerWith(colors: colors, frame: frame, direction: direction)
+        base.layer.insertSublayer(gradientLayer, at: 0)
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/CALayer+Develop.swift b/LingQi/LingQi/Tools/Extensions/CALayer+Develop.swift
new file mode 100644 (file)
index 0000000..956739c
--- /dev/null
@@ -0,0 +1,90 @@
+//
+//  CALayer+HTDevelop.swift
+//  kemiBear
+//
+//  Created by 李扬 on 2017/4/18.
+//  Copyright © 2017年 李扬. All rights reserved.
+//
+
+import UIKit
+
+extension CALayer {
+    
+    
+    /// 给layer添加阴影
+    ///
+    /// - Parameter color:  颜色
+    /// - Parameter blur:   blur radius
+    /// - Parameter opacity: 不透明
+    /// - Parameter rect:   shadowPath
+    ///
+    func addShadow(withRect rect: CGRect, cornerRadius: CGFloat, color: UIColor, blur: CGFloat, opacity: CGFloat) {
+        self.shadowColor = color.cgColor
+        self.shadowRadius = blur
+        self.shadowOpacity = Float(opacity)
+        self.shadowPath = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius).cgPath
+    }
+    
+    func addShadowOffset(color: UIColor, blur: CGFloat, opacity: CGFloat, offset: CGSize) {
+        self.shadowColor = color.cgColor
+        self.shadowRadius = blur
+        self.shadowOpacity = Float(opacity)
+        self.shadowOffset = offset
+    }
+    /// 设置圆角
+//    func setRoundRect() {
+//        self.cornerRadius = self.bounds.size.height * 0.5
+//        self.masksToBounds = true
+//    }
+    /// 设置圆角 角度
+    func setCornerRadius(_ radius:CGFloat) {
+        self.cornerRadius = radius
+        self.masksToBounds = true
+    }
+    
+    /// 设置border
+    func setBorder(width: CGFloat, color: UIColor) {
+        self.borderColor = color.cgColor
+        self.borderWidth = width
+        self.masksToBounds = true
+    }
+    /// layer旋转360°
+    ///
+    /// - Parameter duration: 时间(旋转360度需要的时间)
+    /// - Parameter repeatCount: 重复次数
+    /// - Parameter direction: 方向 CW:顺时针, CCW:逆时针
+    func start360Rotate(duration: TimeInterval, repeatCount: Float = MAXFLOAT, direction: String = "CW") {
+        if let _ = self.animation(forKey: "ly_rotate360Degree") {
+            let pausedTime = self.timeOffset
+            self.speed = 1.0
+            self.timeOffset = 0.0
+            self.beginTime = 0.0
+            let timeSincePause = self.convertTime(CACurrentMediaTime(), from: nil) - pausedTime
+            self.beginTime = timeSincePause
+            return
+        }
+        let rotation = CABasicAnimation.init(keyPath: "transform.rotation.z")
+        rotation.toValue = CGFloat.pi * 2
+        if direction == "CCW" {
+            rotation.toValue = -CGFloat.pi * 2
+        }
+        rotation.duration = duration
+        rotation.repeatCount = repeatCount
+        rotation.isCumulative = true
+        rotation.isRemovedOnCompletion = false
+        rotation.fillMode = CAMediaTimingFillMode.forwards
+        self.speed = 1.0
+        self.add(rotation, forKey: "ly_rotate360Degree")
+    }
+    func pause360Rotate() {
+        guard let _ = self.animation(forKey: "ly_rotate360Degree") else { return }
+        let pauseTime = self.convertTime(CACurrentMediaTime(), from: nil)
+        self.speed = 0
+        self.timeOffset = pauseTime
+    }
+    func stopRotate360() {
+        self.removeAnimation(forKey: "ly_rotate360Degree")
+    }
+}
+
+
diff --git a/LingQi/LingQi/Tools/Extensions/CGRect+HTDevelop.swift b/LingQi/LingQi/Tools/Extensions/CGRect+HTDevelop.swift
new file mode 100644 (file)
index 0000000..13683ed
--- /dev/null
@@ -0,0 +1,96 @@
+//
+//  CGRect+HTDevelop.swift
+//  rrlWallet
+//
+//  Created by gordon on 2018/9/24.
+//  Copyright © 2018 rrl360. All rights reserved.
+//
+
+import UIKit
+
+public extension YCDevelop where Base == CGFloat {
+    func clamp(_ minValue: CGFloat, _ maxValue: CGFloat) -> CGFloat {
+        return base < minValue ? minValue : (base > maxValue ? maxValue : base)
+    }
+}
+
+public extension YCDevelop where Base == CGPoint {
+    func translate(_ dx: CGFloat, dy: CGFloat) -> CGPoint {
+        return CGPoint(x: base.x+dx, y: base.y+dy)
+    }
+    
+    func transform(_ trans: CGAffineTransform) -> CGPoint {
+        return base.applying(trans)
+    }
+    
+    func distance(_ point: CGPoint) -> CGFloat {
+        return sqrt(pow(base.x - point.x, 2)+pow(base.y - point.y, 2))
+    }
+    
+    var transposed: CGPoint {
+        return CGPoint(x: base.y, y: base.x)
+    }
+}
+
+public extension YCDevelop where Base == CGSize {
+    
+    func insets(by insets: UIEdgeInsets) -> CGSize {
+        return CGSize(width: base.width - insets.left - insets.right, height: base.height - insets.top - insets.bottom)
+    }
+    var transposed: CGSize {
+        return CGSize(width: base.height, height: base.width)
+    }
+}
+
+
+/*
+func abs(_ left: CGPoint) -> CGPoint {
+    return CGPoint(x: abs(left.x), y: abs(left.y))
+}
+func min(_ left: CGPoint, _ right: CGPoint) -> CGPoint {
+    return CGPoint(x: min(left.x, right.x), y: min(left.y, right.y))
+}
+func + (left: CGPoint, right: CGPoint) -> CGPoint {
+    return CGPoint(x: left.x + right.x, y: left.y + right.y)
+}
+func += (left: inout CGPoint, right: CGPoint) {
+    left.x += right.x
+    left.y += right.y
+}
+func + (left: CGRect, right: CGPoint) -> CGRect {
+    return CGRect(origin: left.origin + right, size: left.size)
+}
+func - (left: CGPoint, right: CGPoint) -> CGPoint {
+    return CGPoint(x: left.x - right.x, y: left.y - right.y)
+}
+func - (left: CGRect, right: CGPoint) -> CGRect {
+    return CGRect(origin: left.origin - right, size: left.size)
+}
+func / (left: CGPoint, right: CGFloat) -> CGPoint {
+    return CGPoint(x: left.x/right, y: left.y/right)
+}
+func * (left: CGPoint, right: CGFloat) -> CGPoint {
+    return CGPoint(x: left.x*right, y: left.y*right)
+}
+func * (left: CGFloat, right: CGPoint) -> CGPoint {
+    return right * left
+}
+func * (left: CGPoint, right: CGPoint) -> CGPoint {
+    return CGPoint(x: left.x*right.x, y: left.y*right.y)
+}
+prefix func - (point: CGPoint) -> CGPoint {
+    return CGPoint.zero - point
+}
+func / (left: CGSize, right: CGFloat) -> CGSize {
+    return CGSize(width: left.width/right, height: left.height/right)
+}
+func - (left: CGPoint, right: CGSize) -> CGPoint {
+    return CGPoint(x: left.x - right.width, y: left.y - right.height)
+}
+
+prefix func - (inset: UIEdgeInsets) -> UIEdgeInsets {
+    return UIEdgeInsets(top: -inset.top, left: -inset.left, bottom: -inset.bottom, right: -inset.right)
+}
+
+
+*/
diff --git a/LingQi/LingQi/Tools/Extensions/CGSize+Fit.swift b/LingQi/LingQi/Tools/Extensions/CGSize+Fit.swift
new file mode 100644 (file)
index 0000000..27e2a2f
--- /dev/null
@@ -0,0 +1,27 @@
+//
+//  CGSize+Fit.swift
+//  YCDevTools
+//
+//  Created by liangzhenying on 2020/4/30.
+//  Copyright © 2020 zkys. All rights reserved.
+//
+import UIKit
+
+public extension YCDevelop where Base == CGSize {
+    func fit(maxWidth:CGFloat) ->CGSize{
+        var size = base
+        if size.width > maxWidth{
+            size.height = size.height*(maxWidth/size.width)
+            size.width = maxWidth
+        }
+        return size
+    }
+    func fit(maxHeight:CGFloat) ->CGSize{
+        var size = base
+        if size.height > maxHeight{
+            size.width = size.width*(maxHeight/size.height)
+            size.height = maxHeight
+        }
+        return size
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/Codable+Spec.swift b/LingQi/LingQi/Tools/Extensions/Codable+Spec.swift
new file mode 100644 (file)
index 0000000..53305cc
--- /dev/null
@@ -0,0 +1,33 @@
+//
+//  Codable+Spec.swift
+//  zgjd
+//
+//  Created by apple on 2020/12/12.
+//
+
+import Foundation
+
+extension Encodable {
+    
+    public func serialize() throws -> Data {
+        let encoder = JSONEncoder()
+        return try encoder.encode(self)
+    }
+    
+    public func toJSONDic() -> [String: Any]? {
+        var data: Data?
+        if data == nil, let string = self as? String {
+            data = string.data(using: .utf8)
+        }
+        if data == nil {
+            data = try? serialize()
+        }
+        guard let finalData = data else {
+            return nil
+        }
+        guard let jsonObect = try? JSONSerialization.jsonObject(with: finalData, options: .allowFragments) else {
+            return nil
+        }
+        return jsonObect as? [String: Any]
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/CollectionExtensions.swift b/LingQi/LingQi/Tools/Extensions/CollectionExtensions.swift
new file mode 100644 (file)
index 0000000..3cb5c8c
--- /dev/null
@@ -0,0 +1,128 @@
+//
+//  CollectionExtensions.swift
+//  ytxIos
+//
+//  Created by x j z l on 2019/9/12.
+//  Copyright © 2019 spectator. All rights reserved.
+//
+
+#if canImport(Dispatch)
+import Dispatch
+#endif
+
+// MARK: - Methods
+public extension Collection {
+
+    #if canImport(Dispatch)
+    /// SwifterSwift: Performs `each` closure for each element of collection in parallel.
+    ///
+    ///        array.forEachInParallel { item in
+    ///            print(item)
+    ///        }
+    ///
+    /// - Parameter each: closure to run for each element.
+    func forEachInParallel(_ each: (Self.Element) -> Void) {
+        let indicesArray = Array(indices)
+        DispatchQueue.concurrentPerform(iterations: indicesArray.count) { (index) in
+            let elementIndex = indicesArray[index]
+            each(self[elementIndex])
+        }
+    }
+    #endif
+
+    /// SwifterSwift: Safe protects the array from out of bounds by use of optional.
+    ///
+    ///        let arr = [1, 2, 3, 4, 5]
+    ///        arr[safe: 1] -> 2
+    ///        arr[safe: 10] -> nil
+    ///
+    /// - Parameter index: index of element to access element.
+    subscript(safe index: Index) -> Element? {
+        return indices.contains(index) ? self[index] : nil
+    }
+
+}
+
+// MARK: - Methods (Int)
+public extension Collection where Index == Int {
+
+    /// SwifterSwift: Get all indices where condition is met.
+    ///
+    ///     [1, 7, 1, 2, 4, 1, 8].indices(where: { $0 == 1 }) -> [0, 2, 5]
+    ///
+    /// - Parameter condition: condition to evaluate each element against.
+    /// - Returns: all indices where the specified condition evaluates to true. (optional)
+    func indices(where condition: (Element) throws -> Bool) rethrows -> [Index]? {
+        var indicies: [Index] = []
+        for (index, value) in lazy.enumerated() where try condition(value) {
+            indicies.append(index)
+        }
+        return indicies.isEmpty ? nil : indicies
+    }
+
+    /// SwifterSwift: Calls the given closure with an array of size of the parameter slice.
+    ///
+    ///     [0, 2, 4, 7].forEach(slice: 2) { print($0) } -> //print: [0, 2], [4, 7]
+    ///     [0, 2, 4, 7, 6].forEach(slice: 2) { print($0) } -> //print: [0, 2], [4, 7], [6]
+    ///
+    /// - Parameters:
+    ///   - slice: size of array in each interation.
+    ///   - body: a closure that takes an array of slice size as a parameter.
+    func forEach(slice: Int, body: ([Element]) throws -> Void) rethrows {
+        guard slice > 0, !isEmpty else { return }
+
+        var value: Int = 0
+        while value < count {
+            try body(Array(self[Swift.max(value, startIndex)..<Swift.min(value + slice, endIndex)]))
+            value += slice
+        }
+    }
+
+    /// SwifterSwift: Returns an array of slices of length "size" from the array. If array can't be split evenly, the final slice will be the remaining elements.
+    ///
+    ///     [0, 2, 4, 7].group(by: 2) -> [[0, 2], [4, 7]]
+    ///     [0, 2, 4, 7, 6].group(by: 2) -> [[0, 2], [4, 7], [6]]
+    ///
+    /// - Parameter size: The size of the slices to be returned.
+    /// - Returns: grouped self.
+    func group(by size: Int) -> [[Element]]? {
+        //Inspired by: https://lodash.com/docs/4.17.4#chunk
+        guard size > 0, !isEmpty else { return nil }
+        var value: Int = 0
+        var slices: [[Element]] = []
+        while value < count {
+            slices.append(Array(self[Swift.max(value, startIndex)..<Swift.min(value + size, endIndex)]))
+            value += size
+        }
+        return slices
+    }
+
+}
+
+// MARK: - Methods (Integer)
+public extension Collection where Element == IntegerLiteralType, Index == Int {
+
+    /// SwifterSwift: Average of all elements in array.
+    ///
+    /// - Returns: the average of the array's elements.
+    func average() -> Double {
+        // http://stackoverflow.com/questions/28288148/making-my-function-calculate-average-of-array-swift
+        return isEmpty ? 0 : Double(reduce(0, +)) / Double(count)
+    }
+
+}
+
+// MARK: - Methods (FloatingPoint)
+public extension Collection where Element: FloatingPoint {
+
+    /// SwifterSwift: Average of all elements in array.
+    ///
+    ///        [1.2, 2.3, 4.5, 3.4, 4.5].average() = 3.18
+    ///
+    /// - Returns: average of the array's elements.
+    func average() -> Element {
+        guard !isEmpty else { return 0 }
+        return reduce(0, {$0 + $1}) / Element(count)
+    }
+
+}
diff --git a/LingQi/LingQi/Tools/Extensions/ConstraintArrayDSL.swift b/LingQi/LingQi/Tools/Extensions/ConstraintArrayDSL.swift
new file mode 100755 (executable)
index 0000000..982c67d
--- /dev/null
@@ -0,0 +1,350 @@
+//
+//  SnapKitExtend
+//
+//  MIT License
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in all
+//  copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+//  SOFTWARE.
+//
+//  Created by charles on 2017/8/2.
+//  Copyright © 2017年 charles. All rights reserved.
+//
+import SnapKit
+
+public enum ConstraintAxis : Int {
+    case horizontal
+    case vertical
+}
+
+#if os(iOS) || os(tvOS)
+import UIKit
+public typealias ConstraintEdgeInsets = UIEdgeInsets
+#else
+import AppKit
+extension NSEdgeInsets {
+    public static let zero = NSEdgeInsetsZero
+}
+public typealias ConstraintEdgeInsets = NSEdgeInsets
+
+
+#endif
+
+public struct ConstraintArrayDSL {
+    @discardableResult
+    public func prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
+        var constraints = Array<Constraint>()
+        for view in self.array {
+            constraints.append(contentsOf: view.snp.prepareConstraints(closure))
+        }
+        return constraints
+    }
+    
+    public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
+        for view in self.array {
+            view.snp.makeConstraints(closure)
+        }
+    }
+    
+    public func remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
+        for view in self.array {
+            view.snp.remakeConstraints(closure)
+        }
+    }
+    
+    public func updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
+        for view in self.array {
+            view.snp.updateConstraints(closure)
+        }
+    }
+    
+    public func removeConstraints() {
+        for view in self.array {
+            view.snp.removeConstraints()
+        }
+    }
+    
+    /// distribute with fixed spacing
+    ///
+    /// - Parameters:
+    ///   - axisType: which axis to distribute items along
+    ///   - fixedSpacing: the spacing between each item
+    ///   - leadSpacing: the spacing before the first item and the container
+    ///   - tailSpacing: the spacing after the last item and the container
+    public func distributeViewsAlong(axisType:ConstraintAxis, fixedSpacing:CGFloat = 0, leadSpacing:CGFloat = 0, tailSpacing:CGFloat = 0) {
+        
+        guard self.array.count > 1, let tempSuperView = commonSuperviewOfViews() else {
+            return
+        }
+        
+        if axisType == .horizontal {
+            var prev : ConstraintView?
+            for (i, v) in self.array.enumerated() {
+                v.snp.makeConstraints({ (make) in
+                    guard let prev = prev else {//first one
+                        make.left.equalTo(tempSuperView).offset(leadSpacing)
+                        return
+                    }
+                    make.width.equalTo(prev)
+                    make.left.equalTo(prev.snp.right).offset(fixedSpacing)
+                    if (i == self.array.count - 1) {//last one
+                        make.right.equalTo(tempSuperView).offset(-tailSpacing)
+                    }
+                })
+                prev = v;
+            }
+        }else {
+            var prev : ConstraintView?
+            for (i, v) in self.array.enumerated() {
+                v.snp.makeConstraints({ (make) in
+                    guard let prev = prev else {//first one
+                        make.top.equalTo(tempSuperView).offset(leadSpacing);
+                        return
+                    }
+                    make.height.equalTo(prev)
+                    make.top.equalTo(prev.snp.bottom).offset(fixedSpacing)
+                    if (i == self.array.count - 1) {//last one
+                        make.bottom.equalTo(tempSuperView).offset(-tailSpacing);
+                    }
+                })
+                prev = v;
+            }
+        }
+    }
+    
+    /// distribute with fixed item size
+    ///
+    /// - Parameters:
+    ///   - axisType: which axis to distribute items along
+    ///   - fixedItemLength: the fixed length of each item
+    ///   - leadSpacing: the spacing before the first item and the container
+    ///   - tailSpacing: the spacing after the last item and the container
+    public func distributeViewsAlong(axisType:ConstraintAxis, fixedItemLength:CGFloat = 0, leadSpacing:CGFloat = 0, tailSpacing:CGFloat = 0) {
+        
+        guard self.array.count > 1, let tempSuperView = commonSuperviewOfViews() else {
+            return
+        }
+        
+        if axisType == .horizontal {
+            var prev : ConstraintView?
+            for (i, v) in self.array.enumerated() {
+                v.snp.makeConstraints({ (make) in
+                    make.width.equalTo(fixedItemLength)
+                    if prev != nil {
+                        if (i == self.array.count - 1) {//last one
+                            make.right.equalTo(tempSuperView).offset(-tailSpacing);
+                        } else {
+                            let offset = (CGFloat(1) - (CGFloat(i) / CGFloat(self.array.count - 1))) *
+                                (fixedItemLength + leadSpacing) -
+                                CGFloat(i) * tailSpacing / CGFloat(self.array.count - 1)
+                            make.right.equalTo(tempSuperView).multipliedBy(CGFloat(i) / CGFloat(self.array.count - 1)).offset(offset)
+                        }
+                    }else {//first one
+                        make.left.equalTo(tempSuperView).offset(leadSpacing);
+                    }
+                })
+                prev = v;
+            }
+        }else {
+            var prev : ConstraintView?
+            for (i, v) in self.array.enumerated() {
+                v.snp.makeConstraints({ (make) in
+                    make.height.equalTo(fixedItemLength)
+                    if prev != nil {
+                        if (i == self.array.count - 1) {//last one
+                            make.bottom.equalTo(tempSuperView).offset(-tailSpacing);
+                        }else {
+                            let offset = (CGFloat(1) - (CGFloat(i) / CGFloat(self.array.count - 1))) *
+                                (fixedItemLength + leadSpacing) -
+                                CGFloat(i) * tailSpacing / CGFloat(self.array.count - 1)
+                            make.bottom.equalTo(tempSuperView).multipliedBy(CGFloat(i) / CGFloat(self.array.count-1)).offset(offset)
+                        }
+                    }else {//first one
+                        make.top.equalTo(tempSuperView).offset(leadSpacing);
+                    }
+                })
+                prev = v;
+            }
+        }
+    }
+    
+    /// distribute Sudoku with fixed item size
+    ///
+    /// - Parameters:
+    ///   - fixedItemWidth: the fixed width of each item
+    ///   - fixedItemLength: the fixed length of each item
+    ///   - warpCount: the warp count in the super container
+    ///   - edgeInset: the padding in the super container
+    public func distributeSudokuViews(fixedItemWidth: CGFloat, fixedItemHeight: CGFloat, warpCount: Int, edgeInset: ConstraintEdgeInsets = .zero) {
+        
+        guard self.array.count > 1, warpCount >= 1, let tempSuperView = commonSuperviewOfViews() else {
+            return
+        }
+        
+        let remainder = self.array.count % warpCount
+        let quotient = self.array.count / warpCount
+        
+        let rowCount = (remainder == 0) ? quotient : (quotient + 1)
+        let columnCount = warpCount
+        
+        for (i,v) in self.array.enumerated() {
+            
+            let currentRow = i / warpCount
+            let currentColumn = i % warpCount
+            
+            v.snp.makeConstraints({ (make) in
+                make.width.equalTo(fixedItemWidth)
+                make.height.equalTo(fixedItemHeight)
+                if currentRow == 0 {//fisrt row
+                    make.top.equalTo(tempSuperView).offset(edgeInset.top)
+                }
+                if currentRow == rowCount - 1 {//last row
+                    make.bottom.equalTo(tempSuperView).offset(-edgeInset.bottom)
+                }
+                
+                if currentRow != 0 && currentRow != rowCount - 1 {//other row
+                    let offset = (CGFloat(1) - CGFloat(currentRow) / CGFloat(rowCount - 1)) *
+                        (fixedItemHeight + edgeInset.top) -
+                        CGFloat(currentRow) * edgeInset.bottom / CGFloat(rowCount - 1)
+                    make.bottom.equalTo(tempSuperView).multipliedBy(CGFloat(currentRow) / CGFloat(rowCount - 1)).offset(offset);
+                }
+                
+                if currentColumn == 0 {//first col
+                    make.left.equalTo(tempSuperView).offset(edgeInset.left)
+                }
+                if currentColumn == columnCount - 1 {//last col
+                    make.right.equalTo(tempSuperView).offset(-edgeInset.right)
+                }
+                
+                if currentColumn != 0 && currentColumn != columnCount - 1 {//other col
+                    let offset = (CGFloat(1) - CGFloat(currentColumn) / CGFloat(columnCount - 1)) *
+                        (fixedItemWidth + edgeInset.left) -
+                        CGFloat(currentColumn) * edgeInset.right / CGFloat(columnCount - 1)
+                    make.right.equalTo(tempSuperView).multipliedBy(CGFloat(currentColumn) / CGFloat(columnCount - 1)).offset(offset);
+                }
+            })
+        }
+    }
+    
+    /// distribute Sudoku with fixed item spacing
+    ///
+    /// - Parameters:
+    ///   - fixedLineSpacing: the line spacing between each item
+    ///   - fixedInteritemSpacing: the Interitem spacing between each item
+    ///   - warpCount: the warp count in the super container
+    ///   - edgeInset: the padding in the super container
+    public func distributeSudokuViews(fixedLineSpacing: CGFloat, fixedInteritemSpacing: CGFloat, warpCount: Int, edgeInset: ConstraintEdgeInsets = .zero) {
+        
+        guard self.array.count > 1, warpCount >= 1, let tempSuperView = commonSuperviewOfViews() else {
+            return
+        }
+        
+        let remainder = self.array.count % warpCount
+        let quotient = self.array.count / warpCount
+        
+        let rowCount = (remainder == 0) ? quotient : (quotient + 1)
+        let columnCount = warpCount
+        
+        
+        var prev : ConstraintView?
+        
+        for (i,v) in self.array.enumerated() {
+            
+            let currentRow = i / warpCount
+            let currentColumn = i % warpCount
+            
+            v.snp.makeConstraints({ (make) in
+                guard let prev = prev else {//first row & first col
+                    make.top.equalTo(tempSuperView).offset(edgeInset.top)
+                    make.left.equalTo(tempSuperView).offset(edgeInset.left)
+                    return
+                }
+                make.width.height.equalTo(prev)
+                if currentRow == rowCount - 1 {//last row
+                    if currentRow != 0 && i - columnCount >= 0 {//just one row
+                        make.top.equalTo(self.array[i-columnCount].snp.bottom).offset(fixedLineSpacing)
+                    }
+                    make.bottom.equalTo(tempSuperView).offset(-edgeInset.bottom)
+                }
+                
+                if currentRow != 0 && currentRow != rowCount - 1 {//other row
+                    make.top.equalTo(self.array[i-columnCount].snp.bottom).offset(fixedLineSpacing);
+                }
+                if currentColumn == warpCount - 1 {//last col
+                    if currentColumn != 0 {//just one line
+                        make.left.equalTo(prev.snp.right).offset(fixedInteritemSpacing)
+                    }
+                    make.right.equalTo(tempSuperView).offset(-edgeInset.right)
+                }
+                
+                if currentColumn != 0 && currentColumn != warpCount - 1 {//other col
+                    make.left.equalTo(prev.snp.right).offset(fixedInteritemSpacing);
+                }
+            })
+            prev = v
+        }
+    }
+    
+    internal let array: Array<ConstraintView>
+    
+    internal init(array: Array<ConstraintView>) {
+        self.array = array
+    }
+    
+}
+
+public extension Array {
+    var snp: ConstraintArrayDSL {
+        return ConstraintArrayDSL(array: self as! Array<ConstraintView>)
+    }
+}
+
+private extension ConstraintArrayDSL {
+    func commonSuperviewOfViews() -> ConstraintView? {
+        var commonSuperview : ConstraintView?
+        var previousView : ConstraintView?
+        
+        for view in self.array {
+            if previousView != nil {
+                commonSuperview = view.closestCommonSuperview(commonSuperview)
+            }else {
+                commonSuperview = view
+            }
+            previousView = view
+        }
+        
+        return commonSuperview
+    }
+}
+
+private extension ConstraintView {
+    func closestCommonSuperview(_ view : ConstraintView?) -> ConstraintView? {
+        var closestCommonSuperview: ConstraintView?
+        var secondViewSuperview: ConstraintView? = view
+        while closestCommonSuperview == nil && secondViewSuperview != nil {
+            var firstViewSuperview: ConstraintView? = self
+            while closestCommonSuperview == nil && firstViewSuperview != nil {
+                if secondViewSuperview == firstViewSuperview {
+                    closestCommonSuperview = secondViewSuperview
+                }
+                firstViewSuperview = firstViewSuperview?.superview
+            }
+            secondViewSuperview = secondViewSuperview?.superview
+        }
+        return closestCommonSuperview
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/Dictionary+Develop.swift b/LingQi/LingQi/Tools/Extensions/Dictionary+Develop.swift
new file mode 100644 (file)
index 0000000..73ad0c1
--- /dev/null
@@ -0,0 +1,168 @@
+//
+//  Dictionary+LY.swift
+//  teststttt
+//
+//  Created by Gordon on 2017/8/1.
+//  Copyright © 2017年 Gordon. All rights reserved.
+//
+
+import UIKit
+
+// MARK: 字典转字符串
+public extension Dictionary {
+    func toString() -> String? {
+        guard let data = try? JSONSerialization.data(withJSONObject: self,
+                                                     options: []) else {
+            return nil
+        }
+        guard let str = String(data: data, encoding: .utf8) else {
+            return nil
+        }
+        return str
+     }
+    
+}
+
+public extension Dictionary {
+    
+    static func +=(lhs: inout Dictionary<Key, Value>, rhs: Dictionary<Key, Value>)  {
+        lhs.merge(rhs)
+    }
+    mutating func merge<S:Sequence>(_ sequence: S)
+        where S.Iterator.Element == (key: Key, value: Value) {
+            sequence.forEach { self[$0] = $1 }
+        }
+}
+
+public extension YCDevelop where Base == Dictionary<String, String> {
+    var combine2urlParamStr: String {
+        guard base.count > 0 else { return "" }
+        var components = ""
+        for k in base.keys {
+            components.append("\(k)=\(base[k] ?? "")&")
+        }
+        components.removeLast()
+        return components
+    }
+}
+
+public extension YCDevelop where Base == Dictionary<String, Any> {
+    
+    /// 根据key对字典进行排序
+    ///
+    /// - Returns: 数组 第一个为排序之后的key 第二个为排序之后的value
+    private func sortByKeys() -> [[Any]] {
+        if base.count == 0 {
+            return []
+        }
+        let sortedKeys = base.keys.sorted(by: <)
+        var sortedValues = [Any]()
+        sortedKeys.forEach { sortedValues.append(base[$0] ?? "") }
+        return [sortedKeys, sortedValues]
+    }
+    
+    /// 添加签名 kv
+    ///
+    /// - Parameter mix: 添加的用于签名的串
+    /// - Parameter successKey: 签名成功后,添加到字典中的key值 默认为sign
+    /// - Returns: 添加签名kv后的dict
+    func sign(withMix mix: String, successKey: String = "sign") -> [String: Any] {
+        let signature = p_sign(withMix: mix)
+        guard !signature.isEmpty else { return base }
+        var signed = base
+        signed[successKey] = signature
+        return signed
+    }
+    
+    /// 根据kv 生成一个signature
+    private func p_sign(withMix mix: String) -> String {
+        guard base.count > 0 else { return "" }
+        let param = base
+        let arr = param.yc.sortByKeys()
+        guard arr.count == 2 else { return "" }
+        let keys = arr[0]
+        let values = arr[1]
+        var signArr = [String]()
+        for idx in 0 ..< keys.count {
+            let subValue = values[idx]
+            if let value = subValue as? String {
+                var shift = value.replacingOccurrences(of: "\\", with: "\\\\")
+                shift = shift.replacingOccurrences(of: "\0", with: "\\0")
+                shift = shift.replacingOccurrences(of: "\n", with: "\\n")
+                shift = shift.replacingOccurrences(of: "\t", with: "\\t")
+                shift = shift.replacingOccurrences(of: "\r", with: "\\r")
+                shift = shift.replacingOccurrences(of: "\"", with: """
+                \\\"
+                """)
+                signArr.append(#""\#(keys[idx])":"\#(shift)""#)
+            } else if let value = subValue as? [Any] {
+                signArr.append(#""\#(keys[idx])":\#(value.paramSign)"#)
+            } else {
+                signArr.append(#""\#(keys[idx])":\#(subValue)"#)
+            }
+        }
+        let toSignStr = "{" + signArr.joined(separator: ",")
+                        + "}" + "key=\(mix)"
+        k_log(toSignStr)
+        return toSignStr.yc.md5
+    }
+    
+    /// 获取字典所有数据整理后的 签名, 用于比较
+    var signature: String {
+        guard base.count > 0 else { return "" }
+        let arr = base.yc.sortByKeys()
+        guard arr.count == 2 else { return "" }
+        let keys = arr[0]
+        let values = arr[1]
+        var signArr = [String]()
+        for idx in 0 ..< keys.count {
+            let subValue = values[idx]
+            if let value = subValue as? [String: Any] {
+                signArr.append(#""\#(keys[idx])":"\#(value.yc.signature)""#)
+            } else if let value = subValue as? [Any] {
+                signArr.append(#""\#(keys[idx])":"\#(value.signature)""#)
+            } else if let value = subValue as? Bool {
+                signArr.append(#""\#(keys[idx])":"\#(value ? 1 : 0)""#)
+            } else {
+                signArr.append(#""\#(keys[idx])":"\#(subValue)""#)
+            }
+        }
+        return signArr.joined(separator: ",")
+//        return signArr.joined(separator: ",").yc.md5
+    }
+}
+
+fileprivate extension Array {
+    /// 用于数据对比
+    var signature: String {
+        var str = ""
+        for item in self {
+            if let subItem = item as? [Any] {
+                str += subItem.signature
+            } else if let subItem = item as? [String: Any] {
+                str += subItem.yc.signature
+            } else if let subItem = item as? Bool {
+                str += "\(subItem ? 1 : 0)"
+            } else {
+                str += "\(item)"
+            }
+        }
+        return str
+    }
+    /// 用于入参校验
+    var paramSign: String {
+        if self is [[String:Any]] {
+            let data = try? JSONSerialization.data(withJSONObject: self, options: JSONSerialization.WritingOptions.init(rawValue: 0))
+            guard let jsonStr = NSString(data: data!, encoding: String.Encoding.utf8.rawValue) else{
+                return ""
+            }
+            return jsonStr as String
+        }
+        else{
+            let joinedStrng = self.map { #""\#($0)""# }.joined(separator: ",")
+            return "[\(joinedStrng)]"
+        }
+//        let joinedStrng = self.map { #""\#($0)""# }.joined(separator: ",")
+//        return "[\(joinedStrng)]"
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/DispatchQueue+Develop.swift b/LingQi/LingQi/Tools/Extensions/DispatchQueue+Develop.swift
new file mode 100644 (file)
index 0000000..502b49b
--- /dev/null
@@ -0,0 +1,27 @@
+//
+//  DispatchQueue+Develop.swift
+//  YCDevTools
+//
+//  Created by Liang ZhenYing on 2020/3/5.
+//  Copyright © 2020 zkys. All rights reserved.
+//
+
+import UIKit
+
+extension DispatchQueue {
+    
+    private static var onceTracker = [String]()
+    
+    //Executes a block of code, associated with a unique token, only once.  The code is thread safe and will only execute the code once even in the presence of multithreaded calls.
+    public class func once(token: String, block: () -> Void) {
+        /// 保证被 objc_sync_enter 和 objc_sync_exit 包裹的代码可以有序同步地执行
+        objc_sync_enter(self)
+        defer { objc_sync_exit(self) }
+        
+        if onceTracker.contains(token) { return }
+        
+        onceTracker.append(token)
+        block()
+    }
+}
+
diff --git a/LingQi/LingQi/Tools/Extensions/FileManager+Develop.swift b/LingQi/LingQi/Tools/Extensions/FileManager+Develop.swift
new file mode 100644 (file)
index 0000000..0adcff2
--- /dev/null
@@ -0,0 +1,181 @@
+//
+//  FileManager+HTDevelop.swift
+//  rrlWallet
+//
+//  Created by Gordon on 2017/8/2.
+//  Copyright © 2017年 Gordon. All rights reserved.
+//
+
+import UIKit
+import Kingfisher
+
+// MARK: === 各文件目录等
+public extension YCDevelop where Base: FileManager {
+    
+    // MARK: === 获取cachesPath
+    static var libraryCachesPath: String {
+        return NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).first ?? ""
+    }
+    // MARK: === 获取documentPath
+    static var documentPath: String {
+        return NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first ?? ""
+    }
+    // MARK: === 获取下载文件夹目录
+    static var downloadDirectory: String {
+        let path = (libraryCachesPath as NSString).appendingPathComponent("download")
+        if !fileExists(atPath: path) {
+            _ = createDirectories(forPath: path)
+        }
+        return path
+    }
+}
+
+// MARK: === 常用方法
+public extension YCDevelop where Base: FileManager {
+    
+    // MARK: === 文件是否存在
+    static func fileExists(atPath path: String) -> Bool {
+        return FileManager.default.fileExists(atPath:path)
+    }
+    // MARK: === 路径是否是文件夹
+    static func isDirectory(atPath path: String) -> Bool {
+        var isDir:ObjCBool = false
+        FileManager.default.fileExists(atPath: path, isDirectory: &isDir)
+        return isDir.boolValue
+    }
+    // MARK: === 删除文件
+    @discardableResult
+    static func removeItem(atPath path: String) ->  Bool {
+        if let _ = try? FileManager.default.removeItem(atPath: path) {
+            return true
+        }
+        return false
+    }
+    // MARK: === 创建文件夹
+    static func createDirectories(forPath path: String) ->  Bool {
+        guard let _ = try? FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil) else {
+            return false
+        }
+        return true
+    }
+    // MARK: === 获取文件修改时间
+    static func modifyDateOfItem(atPath path: String) -> Date {
+        if let attr = try? FileManager.default.attributesOfItem(atPath: path),
+            let modifyDate = attr[.modificationDate] as? Date {
+            return modifyDate
+        }
+        return Date()
+    }
+    // MARK: === 获取下载文件夹下的 所有目录
+    static func subDownloadDirectories() -> [String] {
+        let download = downloadDirectory
+        guard isDirectory(atPath: download),
+            let dirArr = try? FileManager.default.contentsOfDirectory(atPath: download) else {
+                return []
+        }
+        var subDownloads = [String]()
+        for dir in dirArr {
+            let sub = (dir as NSString).appendingPathComponent(dir)
+            if isDirectory(atPath: sub) {
+                subDownloads.append(sub)
+            }
+        }
+        return subDownloads
+    }
+    // MARK: === 获取文件夹下的所用文件
+    static func fileInDirectory(atPath path: String) -> [String] {
+        guard isDirectory(atPath: path),
+            let dirArr = try? FileManager.default.contentsOfDirectory(atPath: path) else {
+                return []
+        }
+        var subFiles = [String]()
+        
+        for dir in dirArr {
+            let sub = (path as NSString).appendingPathComponent(dir)
+            if !isDirectory(atPath: sub) {
+                subFiles.append(sub)
+            }
+        }
+        return subFiles
+    }
+}
+
+// MARK: - ********* Filepath for AudioPlayer
+extension YCDevelop where Base: FileManager {
+    
+    // MARK: === 文件下载目录
+    static var orderFileDownloadPath: String {
+        let dPath = (documentPath as NSString).appendingPathComponent("orderDownload")
+        if !fileExists(atPath: dPath) {
+            _ = createDirectories(forPath: dPath)
+        }
+        return dPath
+    }
+    // MARK: === 文件下载 URL路径
+    static func orderFileUrl(withFileName name: String) -> URL {
+        let path = orderFileDownloadPath + "/" + name
+        return URL.init(fileURLWithPath: path)
+    }
+    // MARK: === 文件下载 Path路径
+    static func orderFilePath(withFileName name: String) -> String {
+        return orderFileDownloadPath + "/" + name
+    }
+}
+
+
+// MARK: - ********* 缓存统计
+public extension YCDevelop where Base: FileManager {
+    
+    /// 计算文件大小
+    static func foldersSize(atPaths paths: [String]) -> Double {
+        var size = 0.0
+        for path in paths {
+            size = size + folderSize(atPath: path)
+        }
+        return size
+    }
+    
+    private static func folderSize(atPath path: String) -> Double {
+        let manager = FileManager.default
+        guard manager.fileExists(atPath: path) else { return 0 }
+        let childFiles = fileInDirectory(atPath: path)
+        
+        var folderSize:Int64 = 0
+        for childPath in childFiles {
+            folderSize += fileSize(atPath: childPath)
+        }
+        return Double(folderSize)/(1024.0 * 1024.0)
+    }
+    
+    private static func fileSize(atPath path: String) -> Int64 {
+        let manager = FileManager.default
+        if manager.fileExists(atPath: path),
+            let attr = try? manager.attributesOfItem(atPath: path) {
+            return (attr[FileAttributeKey.size] as? Int64) ?? 0
+        }
+        return 0
+    }
+}
+
+
+// MARK: - ********* 清除缓存
+public extension YCDevelop where Base: FileManager {
+    
+    static private var clearPaths: [String] {
+        let kfImgPath = KingfisherManager.shared.cache.diskStorage.directoryURL.absoluteString
+        return [kfImgPath]
+    }
+    static var cacheSize: String {
+        let size = foldersSize(atPaths: clearPaths)
+        return String.init(format: "%.2fM", size)
+    }
+    static var clearCache: Bool {
+        for path in clearPaths {
+            _ = removeItem(atPath: path)
+        }
+        return true
+    }
+}
+
+
+
diff --git a/LingQi/LingQi/Tools/Extensions/KeyPath+Develop.swift b/LingQi/LingQi/Tools/Extensions/KeyPath+Develop.swift
new file mode 100644 (file)
index 0000000..b2e18dc
--- /dev/null
@@ -0,0 +1,35 @@
+//
+//  KeyPath+HTDevelop.swift
+//  HTDevelopTools
+//
+//  Created by 李扬 on 2019/6/4.
+//  Copyright © 2019 Exaleap. All rights reserved.
+//
+
+import UIKit
+
+/*
+public func setter<Object: AnyObject, Value>(
+    for object: Object,
+    keyPath: ReferenceWritableKeyPath<Object, Value>
+    ) -> (Value) -> Void {
+    return { [weak object] value in
+        object?[keyPath: keyPath] = value
+    }
+}
+
+*/
+
+// MARK: - ********* KeyPath method
+public extension Sequence {
+    // MARK: === keyPath map
+    func map<T>(_ keyPath: KeyPath<Element, T>) -> [T] {
+        return map { $0[keyPath: keyPath] }
+    }
+    // MARK: === keyPath sort
+    func sorted<T: Comparable>(by keyPath: KeyPath<Element, T>) -> [Element] {
+        return sorted { a, b in
+            return a[keyPath: keyPath] < b[keyPath: keyPath]
+        }
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/Number+Develop.swift b/LingQi/LingQi/Tools/Extensions/Number+Develop.swift
new file mode 100644 (file)
index 0000000..b7150ae
--- /dev/null
@@ -0,0 +1,19 @@
+//
+//  Number+Develop.swift
+//  YCDevTools
+//
+//  Created by Liang ZhenYing on 2020/3/6.
+//  Copyright © 2020 zkys. All rights reserved.
+//
+
+import UIKit
+
+extension Double {
+    public var π: CGFloat {
+        return CGFloat(self) * CGFloat.pi
+    }
+    
+    public var twoDecimal:String{
+        return String(format: "%.2f", self)
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/QueryParameters.swift b/LingQi/LingQi/Tools/Extensions/QueryParameters.swift
new file mode 100644 (file)
index 0000000..3793c36
--- /dev/null
@@ -0,0 +1,23 @@
+//
+//  QueryParameters.swift
+//  zgjd
+//
+//  Created by apple on 2021/2/20.
+//
+
+import Foundation
+
+extension URL {
+    var queryParameters: QueryParameters { return QueryParameters(url: self) }
+}
+
+class QueryParameters {
+    let queryItems: [URLQueryItem]
+    init(url: URL?) {
+        queryItems = URLComponents(string: url?.absoluteString ?? "")?.queryItems ?? []
+        print(queryItems)
+    }
+    subscript(name: String) -> String? {
+        return queryItems.first(where: { $0.name == name })?.value
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/Sequence+Develop.swift b/LingQi/LingQi/Tools/Extensions/Sequence+Develop.swift
new file mode 100644 (file)
index 0000000..c069fa1
--- /dev/null
@@ -0,0 +1,38 @@
+//
+//  Sequence+HTDevelop.swift
+//  rrlWallet
+//
+//  Created by Gordon on 2017/8/30.
+//  Copyright © 2017年 Gordon. All rights reserved.
+//
+
+import Foundation
+
+public extension Collection {
+    
+    func all(predicate: (Iterator.Element) -> Bool) -> Bool {
+        for x in self where !predicate(x) {
+            return false
+        }
+        return true
+    }
+    
+    /// Finds such index N that predicate is true for all elements up to
+    /// but not including the index N, and is false for all elements
+    /// starting with index N.
+    /// Behavior is undefined if there is no such N.
+    func binarySearch(predicate: (Iterator.Element) -> Bool) -> Index {
+        var low = startIndex
+        var high = endIndex
+        while low != high {
+            let mid = index(low, offsetBy: distance(from: low, to: high)/2)
+            if predicate(self[mid]) {
+                low = index(after: mid)
+            } else {
+                high = mid
+            }
+        }
+        return low
+    }
+}
+
diff --git a/LingQi/LingQi/Tools/Extensions/SignedNumericExtensions.swift b/LingQi/LingQi/Tools/Extensions/SignedNumericExtensions.swift
new file mode 100644 (file)
index 0000000..36cbf9b
--- /dev/null
@@ -0,0 +1,54 @@
+//
+//  SignedNumberExtensions.swift
+//  SwifterSwift
+//
+//  Created by Omar Albeik on 8/15/17.
+//  Copyright © 2017 SwifterSwift
+//
+
+#if canImport(Foundation)
+import Foundation
+#endif
+
+// MARK: - Properties
+public extension SignedNumeric {
+
+    /// SwifterSwift: String.
+    var string: String {
+        return String(describing: self)
+    }
+
+    #if canImport(Foundation)
+    /// SwifterSwift: String with number and current locale currency.
+    var asLocaleCurrency: String? {
+        let formatter = NumberFormatter()
+        formatter.numberStyle = .currency
+        formatter.locale = Locale.current
+        // swiftlint:disable:next force_cast
+        return formatter.string(from: self as! NSNumber)
+    }
+    #endif
+
+}
+
+// MARK: - Methods
+public extension SignedNumeric {
+
+    #if canImport(Foundation)
+    /// SwifterSwift: Spelled out representation of a number.
+    ///
+    ///        print((12.32).spelledOutString()) // prints "twelve point three two"
+    ///
+    /// - Parameter locale: Locale, default is .current.
+    /// - Returns: String representation of number spelled in specified locale language. E.g. input 92, output in "en": "ninety-two"
+    func spelledOutString(locale: Locale = .current) -> String? {
+        let formatter = NumberFormatter()
+        formatter.locale = locale
+        formatter.numberStyle = .spellOut
+
+        guard let number = self as? NSNumber else { return nil }
+        return formatter.string(from: number)
+    }
+    #endif
+
+}
diff --git a/LingQi/LingQi/Tools/Extensions/SnapKit_Extension.swift b/LingQi/LingQi/Tools/Extensions/SnapKit_Extension.swift
new file mode 100755 (executable)
index 0000000..0a89f57
--- /dev/null
@@ -0,0 +1,147 @@
+//
+//  SnapKit_Extension.swift
+//  diandianzanumsers
+//
+//  Created by 楠 on 2017/6/11.
+//  Copyright © 2017年 specddz. All rights reserved.
+//
+
+import Foundation
+import SnapKit
+
+
+extension ConstraintMakerEditable {
+    @discardableResult
+    public func snOffset(_ amount: CGFloat) -> SnapKit.ConstraintMakerEditable {
+        self.offset(amount.fitR)
+        return self
+    }
+
+    @discardableResult
+    public func snInset(_ amount: CGFloat) -> SnapKit.ConstraintMakerEditable {
+        self.inset(amount.fitR)
+        return self
+    }
+    
+}
+
+extension ConstraintMakerRelatable {
+    
+    @discardableResult
+    public func snEqualTo(_ other: ConstraintRelatableTarget, _ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
+        if let other = other as? ConstraintConstantTarget {
+            let value = CGFloat(truncating: other as! NSNumber)
+            return self.equalTo(value.fitR, file, line)
+        } else {
+            
+            return self.equalTo(other, file, line)
+        }
+    }
+    
+    @discardableResult
+    public func snEqualToSuperview(_ file: String = #file, _ line: UInt = #line) -> SnapKit.ConstraintMakerEditable {
+        return self.equalToSuperview(file, line)
+    }
+    
+    @discardableResult
+    public func snTopSuperview(vc: UIViewController,_ file: String = #file, _ line: UInt = #line) -> SnapKit.ConstraintMakerEditable {
+        
+        if #available(iOS 11, *) {
+            return self.equalTo(vc.view.safeAreaLayoutGuide.snp.top)
+        } else {
+            return self.equalTo(vc.topLayoutGuide.snp.bottom)
+        }
+    }
+    
+    @discardableResult
+    public func snTopLessThanSuperview(vc: UIViewController, _ file: String = #file, _ line: UInt = #line) -> SnapKit.ConstraintMakerEditable {
+        if #available(iOS 11, *) {
+            return self.lessThanOrEqualTo(vc.view.safeAreaLayoutGuide.snp.top)
+        } else {
+            return self.lessThanOrEqualTo(vc.topLayoutGuide.snp.bottom)
+        }
+    }
+    
+    @discardableResult
+    public func snTopGreaterThanSuperview(vc: UIViewController, _ file: String = #file, _ line: UInt = #line) -> SnapKit.ConstraintMakerEditable {
+        if #available(iOS 11, *) {
+            return self.greaterThanOrEqualTo(vc.view.safeAreaLayoutGuide.snp.top)
+        } else {
+            return self.greaterThanOrEqualTo(vc.topLayoutGuide.snp.bottom)
+        }
+    }
+    
+    @discardableResult
+    public func snBottomSuperview(vc: UIViewController,_ file: String = #file, _ line: UInt = #line) -> SnapKit.ConstraintMakerEditable {
+        
+        if #available(iOS 11, *) {
+            return self.equalTo(vc.view.safeAreaLayoutGuide.snp.bottom)
+        } else {
+            return self.equalTo(vc.bottomLayoutGuide.snp.top)
+        }
+    }
+    
+    @discardableResult
+    public func snBottomLessThanSuperview(vc: UIViewController,_ file: String = #file, _ line: UInt = #line) -> SnapKit.ConstraintMakerEditable {
+        if #available(iOS 11, *) {
+            return self.lessThanOrEqualTo(vc.view.safeAreaLayoutGuide.snp.bottom)
+        } else {
+            return self.lessThanOrEqualTo(vc.bottomLayoutGuide.snp.top)
+        }
+    }
+    
+    @discardableResult
+    public func snBottomGreaterThanSuperview(vc: UIViewController, _ file: String = #file, _ line: UInt = #line) -> SnapKit.ConstraintMakerEditable {
+        if #available(iOS 11, *) {
+            return self.greaterThanOrEqualTo(vc.view.safeAreaLayoutGuide.snp.bottom)
+        } else {
+            return self.greaterThanOrEqualTo(vc.bottomLayoutGuide.snp.top)
+        }
+    }
+    
+}
+
+public extension ConstraintMaker {
+    
+    func positionCenterY() {
+        self.centerY.snEqualToSuperview()
+    }
+    
+    func positionCenterX() {
+        self.centerX.snEqualToSuperview()
+    }
+    
+    func center() {
+        self.center.snEqualToSuperview()
+    }
+    
+    @discardableResult
+    func height(_ height: CGFloat) -> SnapKit.ConstraintMakerEditable {
+        return self.height.snEqualTo(height)
+    }
+    
+    @discardableResult
+    func width(_ width: CGFloat) -> SnapKit.ConstraintMakerEditable {
+        return self.width.snEqualTo(width)
+    }
+    
+    func size(_ width: ConstraintRelatableTarget, _ height: ConstraintRelatableTarget) {
+        self.width.snEqualTo(width)
+        self.height.snEqualTo(height)
+    }
+    
+    func position(left: CGFloat? = nil, top: CGFloat? = nil, right: CGFloat? = nil, bottom: CGFloat? = nil) {
+        if let target = top {
+            self.top.snEqualToSuperview().snOffset(target)
+        }
+        if let target = left {
+            self.left.snEqualToSuperview().snOffset(target)
+        }
+        if let target = right {
+            self.right.snEqualToSuperview().snOffset(target)
+        }
+        if let target = bottom {
+            self.bottom.snEqualToSuperview().snOffset(target)
+        }
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/String+Attribute.swift b/LingQi/LingQi/Tools/Extensions/String+Attribute.swift
new file mode 100644 (file)
index 0000000..a11a64f
--- /dev/null
@@ -0,0 +1,142 @@
+//
+//  String+HTDevelop.swift
+//  HendersonTouchSwift
+//
+//  Created by Gordon on 2017/6/27.
+//  Copyright © 2017年 taikanglife. All rights reserved.
+//
+
+import UIKit
+
+public extension YCDevelop where Base: NSAttributedString {
+    
+    func size(withConstraints size: CGSize,
+              options: NSStringDrawingOptions = .usesLineFragmentOrigin,
+              context: NSStringDrawingContext? = nil) -> CGSize {
+        let cSize = base.boundingRect(with: size, options: options, context: context).size
+        return CGSize(width: cSize.width.ceil, height: cSize.height.ceil)
+    }
+}
+
+public extension YCDevelop where Base == String {
+    
+    /// string的size
+    func strSize(font: UIFont, constraints size: CGSize, options: NSStringDrawingOptions = .usesLineFragmentOrigin, context: NSStringDrawingContext? = nil) -> CGSize {
+        let cSize = attributedStr(font: font).boundingRect(with: size, options: options, context: context).size
+        return CGSize(width: cSize.width.ceil, height: cSize.height.ceil)
+    }
+    
+    private func attributedStr(font: UIFont) -> NSMutableAttributedString {
+        
+        let attrStr = NSMutableAttributedString.init(string: base)
+        guard base.count > 0 else {
+            return attrStr
+        }
+        let range = NSMakeRange(0, attrStr.length)
+        attrStr.addAttributes([.font: font], range: range)
+        return attrStr
+    }
+   
+    var attr: NSAttributedString {
+        return NSAttributedString.init(string: base)
+    }
+    
+    // MARK: === 字符串添加字间距,行间距
+    ///  字符串添加字间距,行间距(通过转化成AttributedString的方式)
+    ///
+    /// - Parameter font: 文字字体
+    /// - Parameter color: 文字颜色
+    /// - Parameter wordSpacing: 文字间距
+    /// - Parameter lineSpacing: 行间距
+    /// - Parameter lineAlignment: 文字对齐方式
+    ///
+    /// - Returns: 带有字体,颜色,间距的AttributedString
+    func attributedStr(font: UIFont, color: UIColor,
+                       wordSpacing: Float = 0,
+                       lineSpacing: CGFloat = 0,
+                       lineAlignment: NSTextAlignment = .left,
+                       lineBreakMode: NSLineBreakMode? = .byTruncatingTail) -> NSMutableAttributedString {
+        
+        let attr = self.attributedStr(font: font, color: color, wordSpacing: wordSpacing)
+        let paragrapnStyle = NSMutableParagraphStyle()
+        paragrapnStyle.alignment = lineAlignment
+        if let lineBreakMode = lineBreakMode {
+            paragrapnStyle.lineBreakMode = lineBreakMode
+        }
+        let range = NSMakeRange(0, attr.length)
+        if lineAlignment == .justified {
+            attr.addAttributes([.baselineOffset : NSNumber.init(value: 0.0),
+                                .paragraphStyle: paragrapnStyle], range: range)
+        } else {
+            paragrapnStyle.lineSpacing = CGFloat(lineSpacing)
+            attr.addAttribute(.paragraphStyle, value: paragrapnStyle, range: NSMakeRange(0, attr.length))
+        }
+        return attr
+    }
+    
+    private func attributedStr(font: UIFont, color: UIColor, wordSpacing: Float) -> NSMutableAttributedString {
+        
+        let attrStr = NSMutableAttributedString.init(string: base)
+        guard base.count > 0 else {
+            return attrStr
+        }
+        let range = NSMakeRange(0, attrStr.length)
+        attrStr.addAttributes([.font: font,
+                               .foregroundColor: color], range: range)
+        guard wordSpacing != 0 else {
+            return attrStr
+        }
+        attrStr.addAttribute(.kern, value: wordSpacing, range: NSMakeRange(0, attrStr.length - 1))
+        return attrStr
+    }
+    
+    
+    // MARK: === 一行文字两种颜色
+    func attr2Str(font: UIFont,
+                  color: UIColor,
+                  rangeStr: String,
+                  rColor: UIColor,
+                  rFont: UIFont? = nil,
+                  lineAlignment: NSTextAlignment = .left)-> NSMutableAttributedString {
+        let rangeFont = rFont ?? font
+        let attr = self.attributedStr(font: font, color: color, lineAlignment: lineAlignment)
+        let nsStr = NSString.init(string: base)
+        let range = nsStr.range(of: rangeStr)
+        attr.addAttributes([.font: rangeFont,
+                               .foregroundColor: rColor], range: range)
+        return attr
+    }
+    // MARK: === 价格
+    func priceAttr(font1: UIFont,Font2: UIFont,color:UIColor = UIColor.rgb(0xFF4B5A))-> NSMutableAttributedString {
+        let text = "¥" + base
+        let attr = text.yc.attributedStr(font: Font2, color: color, lineAlignment: .left)
+        attr.addAttributes([.font: font1], range: NSRange(location: 0,length: 1))
+        return attr
+    }
+}
+
+public extension YCDevelop where Base: NSMutableAttributedString {
+
+    // MARK: === 给指定文字添加颜色
+    func addAttr(ToStr str: String,
+                 font: UIFont,
+                 color: UIColor) {
+        let nsStr = NSString(string: base.string)
+        let range = nsStr.range(of: str)
+        base.addAttributes([.font: font,
+                            .foregroundColor: color], range: range)
+    }
+    // MARK: === 给文字添加下划线
+    func addUnderLine() {
+        base.addAttributes([.underlineStyle: NSUnderlineStyle.single.rawValue], range: NSMakeRange(0, base.length))
+    }
+    
+    func update(lineAlignment: NSTextAlignment) {
+        
+        let paragrapnStyle = NSMutableParagraphStyle()
+        paragrapnStyle.alignment = lineAlignment
+        base.addAttribute(.paragraphStyle, value: paragrapnStyle, range: NSMakeRange(0, base.length))
+    }
+}
+
+
diff --git a/LingQi/LingQi/Tools/Extensions/String+Develop.swift b/LingQi/LingQi/Tools/Extensions/String+Develop.swift
new file mode 100644 (file)
index 0000000..9825315
--- /dev/null
@@ -0,0 +1,151 @@
+//
+//  String+HTDevelop.swift
+//  HTDevelop
+//
+//  Created by 李扬 on 2019/1/5.
+//  Copyright © 2019 rrl360. All rights reserved.
+//
+
+import UIKit
+
+public extension YCDevelop where Base == String {
+    /// 时间戳格式化为yyyy-MM-dd 时间戳是毫秒
+    var dateFormatString: String {
+        if let interval = TimeInterval(base) {
+            let date = Date(timeIntervalSince1970: interval/1000)
+            let dateformatter = DateFormatter()
+            dateformatter.dateFormat = "yyyy-MM-dd"
+            return dateformatter.string(from: date)
+        }
+        return base
+    }
+    ///  去两边的空格
+    var trimed: String {
+        return base.trimmingCharacters(in: .whitespaces)
+    }
+    ///  将原始的url编码为合法的url
+    var urlEncode: String {
+        return base.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed) ?? base
+    }
+    ///  将编码后的url转换回原始的url
+    var urlDecode: String {
+        return base.removingPercentEncoding ?? base
+    }
+    
+    var isIdentityCard: Bool {
+        //判断是否为空
+        if base.count <= 0 {
+            return false
+        }
+        //判断是否是18位,末尾是否是x
+        let regex2: String = "^(\\d{14}|\\d{17})(\\d|[xX])$"
+        let identityCardPredicate = NSPredicate(format: "SELF MATCHES %@", regex2)
+        if !identityCardPredicate.evaluate(with: base) {
+            return false
+        }
+        //判断生日是否合法
+        let range = NSRange(location: 6, length: 8)
+        let datestr: String = (base as NSString).substring(with: range)
+        let formatter = DateFormatter()
+        formatter.dateFormat = "yyyyMMdd"
+        if formatter.date(from: datestr) == nil {
+            return false
+        }
+        //判断校验位
+        if  base.count == 18 {
+            let idCardWi: [String] = ["7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2"]
+            //将前17位加权因子保存在数组里
+            let idCardY: [String] = ["1", "0", "10", "9", "8", "7", "6", "5", "4", "3", "2"]
+            //这是除以11后,可能产生的11位余数、验证码,也保存成数组
+            var idCardWiSum: Int = 0
+            //用来保存前17位各自乖以加权因子后的总和
+            for i in 0..<17 {
+                idCardWiSum += Int((base as NSString).substring(with: NSRange(location: i, length: 1)))! * Int(idCardWi[i])!
+            }
+            let idCardMod: Int = idCardWiSum % 11
+            //计算出校验码所在数组的位置
+            let idCardLast: String = String(base[base.index(before: base.endIndex)])
+            //得到最后一位身份证号码
+            //如果等于2,则说明校验码是10,身份证号码最后一位应该是X
+            if idCardMod == 2 {
+                if idCardLast == "X" || idCardLast == "x" {
+                    return true
+                } else {
+                    return false
+                }
+            } else {
+                //用计算出的验证码与最后一位身份证号码匹配,如果一致,说明通过,否则是无效的身份证号码
+                if (idCardLast as NSString).integerValue == Int(idCardY[idCardMod]) {
+                    return true
+                } else {
+                    return false
+                }
+            }
+        }
+        return false
+    }
+
+    var isNotEmpty:Bool{
+        return !base.isEmpty
+    }
+    var toJson:Dictionary<String, Any>?{
+        let jsonData:Data = base.data(using: .utf8)!
+        let dict = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)
+        if dict != nil {
+            return dict as? Dictionary<String, Any>
+        }
+        return nil
+    }
+
+
+    var bankCardFormatter: String {
+        let characterSet = NSCharacterSet(charactersIn: "0123456789")
+        let text = base.replacingOccurrences(of: " ", with: "") as NSString
+        var newString = ""
+        let size = text.length/4
+        var tempArr = [String]()
+        
+        for idx in 0..<size {
+            tempArr.append(text.substring(with: NSRange(location: idx*4, length: 4)))
+        }
+        tempArr.append(text.substring(with: NSRange(location: size*4, length: text.length%4)))
+        newString = tempArr.joined(separator: " ")
+        newString = newString.trimmingCharacters(in: characterSet.inverted)
+        return newString
+    }
+    private func getMin(num1 : Int, num2: Int) -> Int {
+        if num1 <= num2 {
+            return num1
+        }else{
+            return num2
+        }
+    }
+    
+    func mobilePhoneRegular() -> String {
+        guard base.yc.isValid(.phone) else { return base }
+        let result = base.prefix(3) + "****" + base.suffix(4)
+        return result.base
+    }
+    
+    /*
+       *去掉首尾空格
+       */
+      var removeHeadAndTailSpace:String {
+          let whitespace = NSCharacterSet.whitespaces
+          return base.trimmingCharacters(in: whitespace)
+      }
+      /*
+       *去掉首尾空格 包括后面的换行 \n
+       */
+      var removeHeadAndTailSpacePro:String {
+          let whitespace = NSCharacterSet.whitespacesAndNewlines
+          return base.trimmingCharacters(in: whitespace)
+      }
+      /*
+       *去掉所有空格
+       */
+      var removeAllSapce: String {
+          return base.replacingOccurrences(of: " ", with: "", options: .literal, range: nil)
+      }
+}
+
diff --git a/LingQi/LingQi/Tools/Extensions/String+Encryption.swift b/LingQi/LingQi/Tools/Extensions/String+Encryption.swift
new file mode 100644 (file)
index 0000000..37f6d99
--- /dev/null
@@ -0,0 +1,286 @@
+//
+//  String+Encryption.swift
+//  rrlWallet
+//
+//  Created by gordon on 2018/3/19.
+//  Copyright © 2018年 rrl360. All rights reserved.
+//
+
+import Foundation
+import CommonCrypto
+
+public extension YCDevelop where Base == String {
+    
+    var base64Encode: String? {
+        if let data = base.data(using: .utf8) {
+            return data.base64EncodedString()
+        }
+        return nil
+    }
+    var base64Decode:String?{
+        guard let data = Data(base64Encoded: base, options: NSData.Base64DecodingOptions.init(rawValue: 0)) else{
+            return nil
+        }
+        let str = String(data: data as Data, encoding: String.Encoding.utf8)
+        return str
+    }
+    var md5: String {
+        guard let data = base.data(using: .utf8) else {
+            return base
+        }
+
+        #if swift(>=5.0)
+        let message = data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) in
+            return [UInt8](bytes)
+        }
+        #else
+        let message = data.withUnsafeBytes { bytes in
+            return [UInt8](UnsafeBufferPointer(start: bytes, count: data.count))
+        }
+        #endif
+
+        let MD5Calculator = MD5(message)
+        let MD5Data = MD5Calculator.calculate()
+
+        var MD5String = String()
+        for c in MD5Data {
+            MD5String += String(format: "%02x", c)
+        }
+        return MD5String
+    }
+}
+
+// array of bytes, little-endian representation
+func arrayOfBytes<T>(_ value: T, length: Int? = nil) -> [UInt8] {
+    let totalBytes = length ?? (MemoryLayout<T>.size * 8)
+
+    let valuePointer = UnsafeMutablePointer<T>.allocate(capacity: 1)
+    valuePointer.pointee = value
+
+    let bytes = valuePointer.withMemoryRebound(to: UInt8.self, capacity: totalBytes) { (bytesPointer) -> [UInt8] in
+        var bytes = [UInt8](repeating: 0, count: totalBytes)
+        for j in 0..<min(MemoryLayout<T>.size, totalBytes) {
+            bytes[totalBytes - 1 - j] = (bytesPointer + j).pointee
+        }
+        return bytes
+    }
+
+    #if swift(>=4.1)
+    valuePointer.deinitialize(count: 1)
+    valuePointer.deallocate()
+    #else
+    valuePointer.deinitialize()
+    valuePointer.deallocate(capacity: 1)
+    #endif
+
+    return bytes
+}
+
+extension Int {
+    // Array of bytes with optional padding (little-endian)
+    func bytes(_ totalBytes: Int = MemoryLayout<Int>.size) -> [UInt8] {
+        return arrayOfBytes(self, length: totalBytes)
+    }
+
+}
+
+extension NSMutableData {
+
+    // Convenient way to append bytes
+    func appendBytes(_ arrayOfBytes: [UInt8]) {
+        append(arrayOfBytes, length: arrayOfBytes.count)
+    }
+
+}
+
+protocol HashProtocol {
+    var message: [UInt8] { get }
+    // Common part for hash calculation. Prepare header data.
+    func prepare(_ len: Int) -> [UInt8]
+}
+
+extension HashProtocol {
+
+    func prepare(_ len: Int) -> [UInt8] {
+        var tmpMessage = message
+
+        // Step 1. Append Padding Bits
+        tmpMessage.append(0x80) // append one bit (UInt8 with one bit) to message
+
+        // append "0" bit until message length in bits ≡ 448 (mod 512)
+        var msgLength = tmpMessage.count
+        var counter = 0
+
+        while msgLength % len != (len - 8) {
+            counter += 1
+            msgLength += 1
+        }
+
+        tmpMessage += [UInt8](repeating: 0, count: counter)
+        return tmpMessage
+    }
+}
+
+func toUInt32Array(_ slice: ArraySlice<UInt8>) -> [UInt32] {
+    var result = [UInt32]()
+    result.reserveCapacity(16)
+
+    for idx in stride(from: slice.startIndex, to: slice.endIndex, by: MemoryLayout<UInt32>.size) {
+        let d0 = UInt32(slice[idx.advanced(by: 3)]) << 24
+        let d1 = UInt32(slice[idx.advanced(by: 2)]) << 16
+        let d2 = UInt32(slice[idx.advanced(by: 1)]) << 8
+        let d3 = UInt32(slice[idx])
+        let val: UInt32 = d0 | d1 | d2 | d3
+
+        result.append(val)
+    }
+    return result
+}
+
+struct BytesIterator: IteratorProtocol {
+
+    let chunkSize: Int
+    let data: [UInt8]
+
+    init(chunkSize: Int, data: [UInt8]) {
+        self.chunkSize = chunkSize
+        self.data = data
+    }
+
+    var offset = 0
+
+    mutating func next() -> ArraySlice<UInt8>? {
+        let end = min(chunkSize, data.count - offset)
+        let result = data[offset..<offset + end]
+        offset += result.count
+        return result.count > 0 ? result : nil
+    }
+}
+
+struct BytesSequence: Sequence {
+    let chunkSize: Int
+    let data: [UInt8]
+
+    func makeIterator() -> BytesIterator {
+        return BytesIterator(chunkSize: chunkSize, data: data)
+    }
+}
+
+func rotateLeft(_ value: UInt32, bits: UInt32) -> UInt32 {
+    return ((value << bits) & 0xFFFFFFFF) | (value >> (32 - bits))
+}
+
+class MD5: HashProtocol {
+
+    static let size = 16 // 128 / 8
+    let message: [UInt8]
+
+    init (_ message: [UInt8]) {
+        self.message = message
+    }
+
+    // specifies the per-round shift amounts
+    private let shifts: [UInt32] = [7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
+                                    5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
+                                    4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
+                                    6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]
+
+    // binary integer part of the sines of integers (Radians)
+    private let sines: [UInt32] = [0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+                                   0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+                                   0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+                                   0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+                                   0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+                                   0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+                                   0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+                                   0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+                                   0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+                                   0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+                                   0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
+                                   0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+                                   0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+                                   0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+                                   0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+                                   0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391]
+
+    private let hashes: [UInt32] = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476]
+
+    func calculate() -> [UInt8] {
+        var tmpMessage = prepare(64)
+        tmpMessage.reserveCapacity(tmpMessage.count + 4)
+
+        // hash values
+        var hh = hashes
+
+        // Step 2. Append Length a 64-bit representation of lengthInBits
+        let lengthInBits = (message.count * 8)
+        let lengthBytes = lengthInBits.bytes(64 / 8)
+        tmpMessage += lengthBytes.reversed()
+
+        // Process the message in successive 512-bit chunks:
+        let chunkSizeBytes = 512 / 8 // 64
+
+        for chunk in BytesSequence(chunkSize: chunkSizeBytes, data: tmpMessage) {
+            // break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15
+            let M = toUInt32Array(chunk)
+            assert(M.count == 16, "Invalid array")
+
+            // Initialize hash value for this chunk:
+            var A: UInt32 = hh[0]
+            var B: UInt32 = hh[1]
+            var C: UInt32 = hh[2]
+            var D: UInt32 = hh[3]
+
+            var dTemp: UInt32 = 0
+
+            // Main loop
+            for j in 0 ..< sines.count {
+                var g = 0
+                var F: UInt32 = 0
+
+                switch j {
+                case 0...15:
+                    F = (B & C) | ((~B) & D)
+                    g = j
+                    break
+                case 16...31:
+                    F = (D & B) | (~D & C)
+                    g = (5 * j + 1) % 16
+                    break
+                case 32...47:
+                    F = B ^ C ^ D
+                    g = (3 * j + 5) % 16
+                    break
+                case 48...63:
+                    F = C ^ (B | (~D))
+                    g = (7 * j) % 16
+                    break
+                default:
+                    break
+                }
+                dTemp = D
+                D = C
+                C = B
+                B = B &+ rotateLeft((A &+ F &+ sines[j] &+ M[g]), bits: shifts[j])
+                A = dTemp
+            }
+
+            hh[0] = hh[0] &+ A
+            hh[1] = hh[1] &+ B
+            hh[2] = hh[2] &+ C
+            hh[3] = hh[3] &+ D
+        }
+        var result = [UInt8]()
+        result.reserveCapacity(hh.count / 4)
+
+        hh.forEach {
+            let itemLE = $0.littleEndian
+            let r1 = UInt8(itemLE & 0xff)
+            let r2 = UInt8((itemLE >> 8) & 0xff)
+            let r3 = UInt8((itemLE >> 16) & 0xff)
+            let r4 = UInt8((itemLE >> 24) & 0xff)
+            result += [r1, r2, r3, r4]
+        }
+        return result
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/String+RegExp.swift b/LingQi/LingQi/Tools/Extensions/String+RegExp.swift
new file mode 100644 (file)
index 0000000..48a4215
--- /dev/null
@@ -0,0 +1,118 @@
+//
+//  String+Regexp.swift
+//  HTDevelop
+//
+//  Created by 李扬 on 2019/1/5.
+//  Copyright © 2019 rrl360. All rights reserved.
+//
+
+import UIKit
+
+public enum RegExpType {
+    case money
+    case telephone
+    case phone
+    case mobile
+    case verifyCode4
+    case verifyCode6
+    case email
+    case identityNo
+    case password
+    case zhWords
+    case enWords
+    case allEnWords
+    case zhAnden
+    case nickName
+    case WeChatCode
+    case AlipayCode
+    case bankCard
+    case custom(String)
+}
+
+public extension YCDevelop where Base == String {
+    
+    // MARK: === 正则校验
+    func isValid(_ type: RegExpType) -> Bool {
+        let predicate = NSPredicate.init(format: "SELF MATCHES %@", type.regStr)
+        return predicate.evaluate(with: base)
+    }
+}
+
+extension RegExpType {
+    var regStr: String {
+        switch self {
+        case .money:
+            return "^[0-9.]"
+            case .telephone:
+                return "0\\d{2,3}-\\d{7,8}|\\(?0\\d{2,3}[)-]?\\d{7,8}|\\(?0\\d{2,3}[)-]*\\d{7,8}"
+        case .phone:
+            return "^1[3456789]\\d{9}$"
+        case .verifyCode4:
+            return "^[0-9]{4}$"
+        case .verifyCode6:
+            return "^[0-9]{6}$"
+        case .mobile:
+//            return "(^1(3[0-9]|4[57]|5[0-35-9]|66|7[6-8]|8[0-9]|9[8-9])\\d{8}$)|(^170[059]\\d{7}$)"
+            return "^[1]([3-9])[0-9]{9}$"
+        case .email:
+            return "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,10}"
+        case .identityNo:
+            return "^(\\d{14}|\\d{17})(\\d|[xX])$"
+//        case .password:
+//            return "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$"
+        case .password:
+            return "^{6,16}$"
+        case .zhWords:
+            return "[\\u4e00-\\u9fa5]+"
+        case .enWords:
+            return "[a-zA-Z0-9]+"
+        case .allEnWords:
+            return "[a-zA-Z]+"
+        case .zhAnden:
+            return "[a-zA-Z0-9\\u4e00-\\u9fa5]+"
+        case .nickName:
+            return "[a-zA-Z0-9\\u4e00-\\u9fa5]{1,15}$"
+        case .WeChatCode:
+            return "^1[012345][0-9]{16}$"
+        case .AlipayCode:
+            return "^(2[56789]|30)[0-9]{14,22}$"
+        case .custom(let str):
+            return str
+        case .bankCard:
+            return "^(\\d{10,30})"
+        }
+    }
+    
+    func customPassword(min: Int,
+                        max: Int,
+                        containDigtal: Bool,
+                        containLetter: Bool,
+                        containCapital: Bool,
+                        containOtherCharacter: Bool,
+                        firstCannotBeDigtal: Bool) -> String {
+        let first = firstCannotBeDigtal ? "^[a-zA-Z_]" : ""
+        let lengthRegex = "(?=^.{\(min),\(max)}$)"
+        let digtalRegex = containDigtal ? "(?=(.*\\d.*){1})" : ""
+        let letterRegex = containLetter ? "(?=(.*[a-z].*){1})" : ""
+        let capitalRegex = containLetter ? "(?=(.*[A-Z].*){1})" : ""
+        let characterRegex = String(format: "(?:%@[A-Za-z0-9%@]+)", first, containOtherCharacter ? containOtherCharacter : "")
+        return lengthRegex + digtalRegex + letterRegex + capitalRegex + characterRegex
+    }
+}
+
+/*
+private let regex_金额 = "^[0-9.]"
+private let regex_手机号 = "^[1][0-9]{10}$"
+private let regex_邮箱 = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,5}"
+private let regex_身份证号 = "^(\\d{14}|\\d{17})(\\d|[xX])$"
+private let regex_密码 = "^[0-9A-Za-z~!@#$^&|*-_+=.?,]{5,20}$"
+
+ // 字母数字下划线
+ "^[0-9a-zA-Z_]{2,20}$"
+ // 字母 数字 汉子
+ "[a-zA-Z0-9\u4e00-\u9fa5]+"
+ // 字母 数字 汉子 特殊符号
+ "[0-9a-zA-Z\u4e00-\u9fa5\\.\\*\\)\\(\\+\\$\\[\\?\\\\\\^\\{\\|\\]\\}%%%@\'\",。‘、-【】·!_——=:;;<>《》‘’“”!#~]+"
+ // 6-15位 大小写字母数字
+ "(?=^.{6,15}$)(?=(.*\\d.*){1})(?=(.*[a-z].*){1})(?=(.*[A-Z].*){1})(?:[A-Za-z0-9!@#$%^&*?\\(\\)]+)"
+ */
diff --git a/LingQi/LingQi/Tools/Extensions/String+SubString.swift b/LingQi/LingQi/Tools/Extensions/String+SubString.swift
new file mode 100644 (file)
index 0000000..8f90172
--- /dev/null
@@ -0,0 +1,45 @@
+//
+//  String+SubString.swift
+//  YCDevTools
+//
+//  Created by liangzhenying on 2020/5/22.
+//  Copyright © 2020 zkys. All rights reserved.
+//
+
+import Foundation
+// MARK: - 字符串截取
+public extension YCDevelop where Base == String{
+    /// String使用下标截取字符串
+    /// string[index] 例如:"abcdefg"[3] // c
+    subscript (i:Int)->String{
+        let startIndex = base.index(base.startIndex, offsetBy: i)
+        let endIndex = base.index(startIndex, offsetBy: 1)
+        return String(base[startIndex..<endIndex])
+    }
+    /// String使用下标截取字符串
+    /// string[index..<index] 例如:"abcdefg"[3..<4] // d
+    subscript (r: Range<Int>) -> String {
+        get {
+            let startIndex = base.index(base.startIndex, offsetBy: r.lowerBound)
+            let endIndex = base.index(base.startIndex, offsetBy: r.upperBound)
+            return String(base[startIndex..<endIndex])
+        }
+    }
+    /// String使用下标截取字符串
+    /// string[index,length] 例如:"abcdefg"[3,2] // de
+    subscript (index:Int , length:Int) -> String {
+        get {
+            let startIndex = base.index(base.startIndex, offsetBy: index)
+            let endIndex = base.index(startIndex, offsetBy: length)
+            return String(base[startIndex..<endIndex])
+        }
+    }
+    // 截取 从头到i位置
+    func substring(to:Int) -> String{
+        return self[0..<to]
+    }
+    // 截取 从i到尾部
+    func substring(from:Int) -> String{
+        return self[from..<base.count]
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/String+Week.swift b/LingQi/LingQi/Tools/Extensions/String+Week.swift
new file mode 100644 (file)
index 0000000..1f730d0
--- /dev/null
@@ -0,0 +1,156 @@
+//
+//  String+Week.swift
+//  zgjd
+//
+//  Created by memory on 2021/4/23.
+//
+
+import Foundation
+
+
+
+public extension YCDevelop where Base == String {
+    enum WeekDay {
+        case Mon
+        case Tue
+        case Wed
+        case Thur
+        case Fri
+        case Sat
+        case Sun
+        
+        var value:Int{
+            switch self {
+            case .Mon:
+                return 1
+            case .Tue:
+                return 2
+            case .Wed:
+                return 3
+            case .Thur:
+                return 4
+            case .Fri:
+                return 5
+            case .Sat:
+                return 6
+            case .Sun:
+                return 7
+            }
+        }
+        var name:String{
+            switch self {
+            case .Mon:
+                return "周一"
+            case .Tue:
+                return "周二"
+            case .Wed:
+                return "周三"
+            case .Thur:
+                return "周四"
+            case .Fri:
+                return "周五"
+            case .Sat:
+                return "周六"
+            case .Sun:
+                return "周日"
+            }
+        }
+        /// 判断nextDay是否是相连的
+        func isNear(nextDay:WeekDay) ->Bool{
+            return self.value + 1 == nextDay.value
+        }
+    }
+    
+    //周一,周二,周日,周六,周五,周三,周四 改成周一至周日
+    func weekFormater() -> String{
+        let text = base
+        var days = text.split(separator: ",").map{String($0).yc.week()}
+        days.sort { (item1, item2) -> Bool in
+            return item1.value < item2.value
+        }
+        k_log(days)
+        if days.count <= 1 {
+            return text
+        }
+        else if days.count == 7{
+            return "周一至周日"
+        }
+        else{
+//            let sum = days.map{$0.name}.joined(separator: ",")
+//            return sum
+            return text
+        }
+    }
+//    //周一,周二,周日,周六,周五,周三,周四 改成周一至周日
+//    func weekFormater() -> String{
+////        let test = "周一,周二,周日,周六,周五,周三,周四"
+//        let test = "周一,周二,周日,周五,周四"
+//        var days = test.split(separator: ",").map{String($0).yc.week()}
+//        days.sort { (item1, item2) -> Bool in
+//            return item1.value < item2.value
+//        }
+//        k_log(days)
+//        if days.count == 0 {
+//            return test
+//        }
+//        var section = [[WeekDay]]()
+//        let count = days.count
+//
+//        var i = 0
+//        while  i < count - 1 {
+//            var row = [WeekDay]()
+//            var current = days[i]
+//            row.append(current)
+//            for j in i+1 ..< count {
+//                let next = days[j]
+//                if current.isNear(nextDay: next){
+//                    current = next
+//                    row.append(next)
+//                    if j == count - 1 {
+//                        i = j
+//                        break
+//                    }
+//                }
+//                else{
+//                    i = j
+//                    break
+//                }
+//            }
+//            section.append(row)
+//        }
+//
+//        var textList = [String]()
+//        for row in section {
+//            if row.count == 1 {
+//                textList.append(row.first!.name)
+//            }
+//            else if row.count > 1 {
+//                let text = row.first!.name + "至" + row.last!.name
+//                textList.append(text)
+//            }
+//        }
+//        let sum = textList.joined(separator: ",")
+//        return sum
+//    }
+
+    private func week() -> WeekDay {
+        switch base {
+        case "周一":
+            return .Mon
+        case "周二":
+            return .Tue
+        case "周三":
+            return .Wed
+        case "周四":
+            return .Thur
+        case "周五":
+            return .Fri
+        case "周六":
+            return .Sat
+        case "周日":
+            return .Sun
+        default:
+            return .Mon
+        }
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/String+YL.swift b/LingQi/LingQi/Tools/Extensions/String+YL.swift
new file mode 100644 (file)
index 0000000..b46db1d
--- /dev/null
@@ -0,0 +1,13 @@
+//
+//  File.swift
+//  zgjd
+//
+//  Created by apple on 2020/11/12.
+//
+
+import Foundation
+extension String{
+    var isNotEmpty:Bool{
+        return !self.isEmpty
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/StringURL+Develop.swift b/LingQi/LingQi/Tools/Extensions/StringURL+Develop.swift
new file mode 100644 (file)
index 0000000..53854c4
--- /dev/null
@@ -0,0 +1,62 @@
+//
+//  URL+HTDevelop.swift
+//  rrlWallet
+//
+//  Created by gordon on 2018/10/26.
+//  Copyright © 2018 rrl360. All rights reserved.
+//
+
+import UIKit
+
+public extension YCDevelop where Base == String {
+    
+    /// to URL?
+    var asUrl: URL? { return URL(string: base.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? base) }
+    
+    /// 获取url?后面的参数
+    var urlQueries: [String: String] {
+        let urlPaths = base.components(separatedBy: "?")
+        guard urlPaths.count == 2 else { return [:] }
+        let paths = urlPaths[1].components(separatedBy: "&")
+        var queries = [String: String]()
+        for q in paths {
+            if let k = q.range(of: "=") {
+                let kStr = q[..<k.lowerBound]
+                let vStr = q[k.upperBound...]
+                queries["\(kStr)"] = "\(vStr)"
+            }
+        }
+        return queries
+    }
+//    /// 重新拼接url  并加上校验位
+//    var urlReverify: String {
+//        guard !base.isEmpty else { return "" }
+//        var addParam = ["appToken": RRUserDefaults.token,
+//                        "appVersion": RRAppInfo.appCurVersion,
+//                        "AppManagerid": RRUserDefaults.user_id,
+//                        "appWechatimage": RRUserDefaults.wechatimage,
+//                        "AppManagerimage": RRUserDefaults.userimage]
+//        /// 如果url本身带有参数
+//        if base.contains("?") {
+//            let urlPaths = base.components(separatedBy: "?")
+//            guard urlPaths.count == 2 else { return base }
+//            let queries = urlPaths[1].yc.urlQueries
+//            addParam.ly_merge(queries)
+//            let verifyStr = addParam.yc.appVerifyStr
+//            let appendParam = ["appToken": RRUserDefaults.token,
+//                               "appVersion": RRAppInfo.appCurVersion,
+//                               "appr": "\(999999.yc.randomNum)",
+//                               "appver": verifyStr]
+//            let appendUrlQuery = appendParam.yc.appendUrlComponents
+//            return base + "&" + appendUrlQuery
+//        }
+//        /// url本身没有参数
+//        let verifyStr = addParam.yc.appVerifyStr
+//        addParam["appr"] = "\(999999.yc.randomNum)"
+//        addParam["appver"] = verifyStr
+//        let appendUrlQuery = addParam.yc.appendUrlComponents
+//        return base + "?" + appendUrlQuery
+//    }
+}
+
+
diff --git a/LingQi/LingQi/Tools/Extensions/Time+Develop.swift b/LingQi/LingQi/Tools/Extensions/Time+Develop.swift
new file mode 100644 (file)
index 0000000..6da04fe
--- /dev/null
@@ -0,0 +1,99 @@
+//
+//  TimeInterval+HTDevelop.swift
+//  rrlWallet
+//
+//  Created by Gordon on 2017/8/10.
+//  Copyright © 2017年 Gordon. All rights reserved.
+//
+
+import Foundation
+import SwiftDate
+
+public extension YCDevelop where Base == Int {
+    
+    var timeString: String {
+        let seconds = base
+        let hour_str = String.init(format: "%02d", seconds/3600)
+        let minute_str = String.init(format: "%02d", (seconds%3600)/60)
+        let second_str = String.init(format: "%02d", seconds%60)
+//        if hour_str == "00" {
+//            return "\(minute_str):\(second_str)"
+//        }
+        return "\(hour_str):\(minute_str):\(second_str)"
+    }
+    var hmTimeString: String {
+        let seconds = base
+        let hour_str = String.init(format: "%02d", seconds/3600)
+        let minute_str = String.init(format: "%02d", (seconds%3600)/60)
+//        let second_str = String.init(format: "%02d", seconds%60)
+//        if hour_str == "00" {
+//            return "\(minute_str):\(second_str)"
+//        }
+        return "\(hour_str)时\(minute_str)分"
+    }
+}
+
+public extension YCDevelop where Base == TimeInterval {
+    
+    var timeString: String {
+        return Int(base).yc.timeString
+    }
+}
+import SwiftDate
+public extension YCDevelop where Base == Date {
+    
+    /// 获取当前 -> 上午/中午/下午/晚上
+    static var timePeriod: String {
+        let hour = DateInRegion(Date(), region: .local).hour
+        switch hour {
+        case 6 ..< 10:
+            return "早上"
+        case 10 ..< 14:
+            return "中午"
+        case 14 ... 18:
+            return "下午"
+        default:
+            return "晚上"
+        }
+    }
+    
+    /// 获取当前 秒级 时间戳 - 10位
+    static var timeStamp : String {
+        let timeInterval: TimeInterval = Date().timeIntervalSince1970
+        let timeStamp = Int(timeInterval)
+        return "\(timeStamp)"
+    }
+    
+    /// 获取当前 毫秒级 时间戳 - 13位
+    static var milliStamp : String {
+        let timeInterval: TimeInterval = Date().timeIntervalSince1970
+        let millisecond = CLongLong(round(timeInterval*1000))
+        return "\(millisecond)"
+    }
+
+    /// 获取当前时间 (2020-02-02 02:02:02)
+    static var currentTime : String {
+        let dformatter = DateFormatter()
+        dformatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
+        let datestr = dformatter.string(from: Date())
+        return datestr
+    }
+    /// 获取当前日期 (02-02 )
+    static var currentDate : String {
+        let dformatter = DateFormatter()
+        dformatter.dateFormat = "MM-dd"
+        let datestr = dformatter.string(from: Date())
+        return datestr
+    }
+}
+
+public extension YCDevelop where Base == String {
+    func toDate(formatter:String) ->Date?{
+        let df = DateFormatter()
+        df.timeZone = TimeZone.current
+        df.dateFormat = formatter
+        let date = df.date(from: base)
+        return date
+    }
+}
+
diff --git a/LingQi/LingQi/Tools/Extensions/UIApplication+Develop.swift b/LingQi/LingQi/Tools/Extensions/UIApplication+Develop.swift
new file mode 100644 (file)
index 0000000..a596bbc
--- /dev/null
@@ -0,0 +1,65 @@
+//
+//  UIApplication+HTDevelop.swift
+//  rrlWallet
+//
+//  Created by Gordon on 2018/3/1.
+//  Copyright © 2018年 rrl360. All rights reserved.
+//
+
+import UIKit
+
+public extension YCDevelop where Base: UIViewController {
+
+    static var currentVC: UIViewController? {
+        return getTopVC(withRootVC: UIApplication.yc.keyWindow?.rootViewController)
+    }
+    static var currentNav: UINavigationController? {
+        return currentVC?.navigationController
+    }
+}
+
+public extension YCDevelop where Base: UIApplication {
+    
+    static var keyWindow: UIWindow? {
+        return UIApplication.shared.keyWindow
+//        var window: UIWindow? = nil
+//        if #available(iOS 13.0, *) {
+//            let scenes = UIApplication.shared.connectedScenes as? Set<UIWindowScene> ?? []
+//            for scene in scenes where scene.activationState == .foregroundActive {
+//                window = scene.windows.first
+//                break
+//            }
+//            return window
+//        } else {
+//            return UIApplication.shared.keyWindow
+//        }
+    }
+    
+    static var currentVC: UIViewController? {
+        guard
+            let tabbarVC = keyWindow?.rootViewController as? UITabBarController
+            else { return nil }
+        return getTopVC(withRootVC: tabbarVC)
+    }
+    
+    static var currentNav: UINavigationController? {
+        return currentVC?.navigationController
+    }
+}
+
+private func getTopVC(withRootVC rootVC: UIViewController?) -> UIViewController? {
+    guard let root = rootVC else { return nil }
+    if root is UITabBarController {
+        return getTopVC(withRootVC: (root as? UITabBarController)?.selectedViewController)
+    }
+    else if root is UINavigationController {
+        return getTopVC(withRootVC: (root as? UINavigationController)?.visibleViewController)
+    }
+    else if let modalVC = root.presentedViewController {
+        return getTopVC(withRootVC: modalVC)
+    }
+    else {
+        return root
+    }
+}
+
diff --git a/LingQi/LingQi/Tools/Extensions/UIButton+Develop.swift b/LingQi/LingQi/Tools/Extensions/UIButton+Develop.swift
new file mode 100644 (file)
index 0000000..8b76f86
--- /dev/null
@@ -0,0 +1,130 @@
+//
+//  UIButton+HTDevelop.swift
+//  rrlWallet
+//
+//  Created by Gordon on 2018/2/28.
+//  Copyright © 2018年 rrl360. All rights reserved.
+//
+
+import UIKit
+
+public enum HTImagePosition {
+    ///  图片在左,文字在右
+    case left
+    ///  图片在右,文字在左
+    case right
+    ///  图片在上,文字在下
+    case top
+    ///  图片在下,文字在上
+    case bottom
+}
+
+public extension YCDevelop where Base: UIButton {
+    
+    /// 设置button中图片文字的位置
+    /// - Requires:
+    ///    * (imageView & titleLabel) both initialized
+    ///    * `top` & `bottom` need a pre final Width & Height Constraint
+    /// - Parameters:
+    ///   - position: 图片位置
+    ///   - spacing:  间距
+    func setImagePosition(_ position: HTImagePosition, spacing: CGFloat) {
+        guard let label = base.titleLabel else { return }
+        let title = label.text ?? ""
+        let imageSize = base.imageView?.image?.size ?? .zero
+        let constraints = CGSize(width: base.width, height: base.height)
+        let imgWid = imageSize.width
+        let imgHei = imageSize.height
+        let txtSize = title.yc.strSize(font: label.font, constraints: constraints)
+        let txtWid = txtSize.width
+        let txtHei = txtSize.height
+        
+        switch position {
+        case .left:
+            base.imageEdgeInsets = UIEdgeInsets(top: 0,
+                                                left: -spacing.half,
+                                                bottom: 0,
+                                                right: spacing.half)
+            base.titleEdgeInsets = UIEdgeInsets(top: 0,
+                                                left: spacing.half,
+                                                bottom: 0,
+                                                right: -spacing.half)
+        case .right:
+            base.imageEdgeInsets = UIEdgeInsets(top: 0,
+                                                left: txtWid + spacing.half,
+                                                bottom: 0,
+                                                right: -(txtWid + spacing.half))
+            base.titleEdgeInsets = UIEdgeInsets(top: 0,
+                                                left: -(imgWid + spacing.half),
+                                                bottom: 0,
+                                                right: imgWid + spacing.half)
+        case .top:
+//            let imageLeft = max(imgWid, txtWid).half - imgWid.half
+//            let titleLeft = (max(imgWid, txtWid) - txtWid).half + min(imgWid, txtWid)
+//            let totalHei = imgHei + txtHei + spacing
+//            let imageTop = (base.height - totalHei).half
+//            let imageBtm =  base.height - (imageTop + imgHei) - spacing.half
+//            let titleTop = imageTop + imgHei + spacing.half
+//            let titleBtm = -imageTop
+//            base.imageEdgeInsets = UIEdgeInsets(top: imageTop,
+//                                                left: imageLeft,
+//                                                bottom: imageBtm,
+//                                                right: -imageLeft)
+//            base.titleEdgeInsets = UIEdgeInsets(top: titleTop,
+//                                                left: -titleLeft,
+//                                                bottom: titleBtm,
+//                                                right: titleLeft)
+            let imageLeft = (constraints.width - imgWid).half
+            let totalHei = imgHei + txtHei + spacing
+            let imageTop = (constraints.height - totalHei).half
+            let imageBtm =  constraints.height - (imageTop + imgHei) - spacing.half
+            let titleTop = imageTop + imgHei + spacing.half
+            let titleBtm = -imageTop
+            base.imageEdgeInsets = UIEdgeInsets(top: imageTop,
+                                                left: imageLeft,
+                                                bottom: imageBtm,
+                                                right: -imageLeft)
+            base.titleEdgeInsets = UIEdgeInsets(top: titleTop,
+                                                left: -imgWid,
+                                                bottom: titleBtm,
+                                                right: 0)
+        case .bottom:
+            let imageLeft = max(imgWid, txtWid).half - imgWid.half
+            let totalHei = imgHei + txtHei + spacing
+            let titleTop = (base.height - totalHei).half
+            let titleBtm =  base.height - (titleTop + txtHei) - spacing.half
+            let imageTop = titleTop + txtHei + spacing.half
+            let imageBtm = -titleTop
+            base.imageEdgeInsets = UIEdgeInsets(top: imageTop,
+                                                left: imageLeft,
+                                                bottom: imageBtm,
+                                                right: -imageLeft)
+            base.titleEdgeInsets = UIEdgeInsets(top: titleTop,
+                                                left: -imgWid,
+                                                bottom: titleBtm,
+                                                right: 0)
+        }
+    }
+    
+    
+    /// 交换imageview和label的位置
+    func exchangeLabelAndImagePosition(interval: CGFloat) {
+        let imageW = (base.imageView?.bounds.width ?? 0.0) + interval * 0.5
+        let lableW = (base.titleLabel?.bounds.width ?? 0.0) + interval * 0.5
+        base.titleEdgeInsets = UIEdgeInsets(top: 0, left: -imageW, bottom: 0, right: imageW)
+        base.imageEdgeInsets = UIEdgeInsets(top: 0, left: lableW, bottom: 0, right: -lableW)
+    }
+    /// 设置imageview和label的间距
+    func setLabelAndImageInterval(_ interval: CGFloat) {
+        base.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: interval)
+        base.titleEdgeInsets = UIEdgeInsets(top: 0, left: interval, bottom: 0, right: 0)
+    }
+    
+    func clearImageLabelInsets() {
+        base.titleEdgeInsets = UIEdgeInsets.zero
+        base.imageEdgeInsets = UIEdgeInsets.zero
+    }
+    
+}
+
+
diff --git a/LingQi/LingQi/Tools/Extensions/UIDevice+Landscape.swift b/LingQi/LingQi/Tools/Extensions/UIDevice+Landscape.swift
new file mode 100644 (file)
index 0000000..31738c1
--- /dev/null
@@ -0,0 +1,16 @@
+//
+//  UIDevice+Landscape.swift
+//  LandscapeDemo
+//
+//  Created by memory on 2021/4/12.
+//
+
+import UIKit
+extension UIDevice{
+    static func switchOrientation(orientation :UIInterfaceOrientation){
+        let value = orientation.rawValue
+        if UIDevice.current.responds(to: #selector(setValue(_:forKey:))) {
+            UIDevice.current.setValue(value, forKey: "orientation")
+        }
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/UIImage+Develop.swift b/LingQi/LingQi/Tools/Extensions/UIImage+Develop.swift
new file mode 100644 (file)
index 0000000..ff013a1
--- /dev/null
@@ -0,0 +1,236 @@
+//
+//  UIImage+Develop.swift
+//  YCDevTools
+//
+//  Created by Liang ZhenYing on 2020/3/5.
+//  Copyright © 2020 zkys. All rights reserved.
+//
+
+import UIKit
+import Photos
+import AssetsLibrary
+
+public extension YCDevelop where Base: UIImage {
+    
+    /// 返回一张带有颜色尺寸带圆角的 image
+    static func image(color:UIColor, size: CGSize, cornerRadius: CGFloat) -> UIImage {
+        
+        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
+        let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius)
+        path.lineWidth = 0
+        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
+        let context = UIGraphicsGetCurrentContext()
+        context?.setFillColor(color.cgColor)
+        path.fill()
+        path.stroke()
+        path.addClip()
+        
+        let img = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+        return img!
+    }
+    
+    /// 返回一张带有颜色尺寸带 自定义圆角的 image
+    static func image(withCorners corners: UIRectCorner, color:UIColor, size: CGSize, cornerRadius: CGFloat) -> UIImage {
+        
+        let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
+        let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))
+        path.lineWidth = 0
+        UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
+        let context = UIGraphicsGetCurrentContext()
+        context?.setFillColor(color.cgColor)
+        path.fill()
+        path.stroke()
+        path.addClip()
+        
+        let img = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+        return img!
+    }
+    
+    static func isEqual(lhs: UIImage, rhs: UIImage) -> Bool {
+        guard let data1 = lhs.pngData(),
+            let data2 = rhs.pngData() else {
+                return false
+        }
+        return data1 == data2
+    }
+    
+    ///  裁剪图片 -> 方形图片
+    func squareImg() -> UIImage {
+        let wid = base.size.width
+        let hei = base.size.height
+        var n_x = (wid - hei) * 0.5
+        var n_y:CGFloat = 0
+        var n_w = hei
+        var n_h = hei
+        if wid < hei {
+            n_x = 0
+            n_y = (hei - wid) * 0.5
+            n_w = wid
+            n_h = wid
+        }
+        let rect = CGRect.init(x: n_x, y: n_y, width: n_w, height: n_h)
+        guard let newImg = base.cgImage?.cropping(to: rect) else { return UIImage() }
+        return UIImage.init(cgImage: newImg)
+    }
+}
+
+public extension YCDevelop where Base: UIImage {
+    
+    /// 改变图标的颜色,用于小图标绘制
+    /// ## 只用于纯色图标 ##
+    /// - Parameter tintColor: 目标颜色
+    ///
+    /// - Returns: 改变颜色后的image
+    func tint(_ tintColor: UIColor) -> UIImage {
+        UIGraphicsBeginImageContextWithOptions(base.size, false, 0)
+        tintColor.setFill()
+        let bounds = CGRect.init(x: 0, y: 0, width: base.size.width, height: base.size.height)
+        UIRectFill(bounds)
+        base.draw(in: bounds, blendMode: .destinationIn, alpha: 1)
+        let tintedImage = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+        return tintedImage!
+    }
+    
+    /// 缩小图片大小
+    func scale(to newSize: CGSize) -> UIImage {
+        guard base.size != newSize else { return base }
+        let scaledRect = fixPictureSize(newSize: newSize)
+        UIGraphicsBeginImageContextWithOptions(scaledRect.size, false, UIScreen.main.scale)
+        defer { UIGraphicsEndImageContext() }
+        base.draw(in: scaledRect)
+        return UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
+    }
+    private func fixPictureSize(newSize: CGSize) -> CGRect {
+        let ratio = max(newSize.width / base.size.width,
+                        newSize.height / base.size.height)
+        let width = base.size.width * ratio
+        let height = base.size.height * ratio
+        let scaledRect = CGRect(x: 0, y: 0,
+                                width: width, height: height)
+        return scaledRect
+    }
+    
+    /// 给图片切圆角
+    func drawRectWithRoundedCorner(radius: CGFloat, _ sizetoFit: CGSize) -> UIImage {
+        guard radius > 0 else { return base }
+        let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: sizetoFit)
+        UIGraphicsBeginImageContextWithOptions(rect.size, false, UIScreen.main.scale)
+        let context = UIGraphicsGetCurrentContext()!
+        let path = UIBezierPath(roundedRect: rect, cornerRadius: radius).cgPath
+        context.addPath(path)
+        context.clip()
+        base.draw(in: rect)
+        context.drawPath(using: .fillStroke)
+        defer { UIGraphicsEndImageContext() }
+        return UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
+    }
+}
+
+// MARK: - ********* 压缩图片
+public extension YCDevelop where Base: UIImage {
+    
+    /// 压缩图片大小
+    ///  分享图片 使用此方法压缩
+    /// - Parameter size: 压缩后的大小(单位:k) 默认32k
+    /// - Returns: 压缩好的图片
+    func compressTo(_ size: Int = 32) -> Data? {
+        
+        let maxFileSize = size * 1000
+        var compression: CGFloat = 1
+        
+        guard var compressedData = base.jpegData(compressionQuality: compression) else { return nil }
+        compression = 0.95
+        while compressedData.count > maxFileSize {
+            compression = 0.95 * compression
+            let toCompressImg = scaleCompress(toWidth: base.size.width * compression)
+            compressedData = toCompressImg.jpegData(compressionQuality: compression)!
+        }
+        return compressedData
+    }
+    
+    /// 等比缩放本图片大小
+    ///
+    /// - Parameter toWidth: 缩放后图片宽度,像素为单位
+    /// - Returns: 缩放后的图片
+    private func scaleCompress(toWidth wid: CGFloat) -> UIImage {
+        
+        let imgW = base.size.width
+        let imgH = base.size.height
+        let newW = wid
+        let newH = imgH / (imgW / newW)
+        let wScale = imgW / newW
+        let hScale = imgH / newH
+        
+        UIGraphicsBeginImageContext(.init(width: newW, height: newH))
+        if wScale > hScale {
+            base.draw(in: .init(x: 0, y: 0, width: imgW/hScale, height: newH))
+        } else {
+            base.draw(in: .init(x: 0, y: 0, width: newW, height: imgH/wScale))
+        }
+        let newImg = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+        return newImg ?? UIImage()
+    }
+}
+
+// MARK: - ********* 相册
+//public extension YCDevelop where Base: UIImage {
+//    // MARK: === 保存到相册
+//    func save2Album(_ isPermitted: ((Bool) -> Void)? = nil, _ callback: ((Bool) -> Void)?) {
+//        let img = base
+//        YCPermissions.authorizePhoto(comletion: { (permit) in
+//            if permit {
+//                PHPhotoLibrary.shared().performChanges({
+//                    PHAssetChangeRequest.creationRequestForAsset(from: img)
+//                }) { (isSuccess, _) in
+//                    DispatchQueue.main.async {
+//                        callback?(isSuccess)
+//                    }
+//                }
+//                isPermitted?(true)
+//            } else {
+//                YCPermissions.alertNoPermission(.photo)
+//                isPermitted?(false)
+//            }
+//        })
+//    }
+//}
+
+
+//extension UIImage {
+//
+//    func imageWith(newSize: CGSize) -> UIImage {
+//        let renderer = UIGraphicsImageRenderer(size: newSize)
+//        let image = renderer.image {_ in
+//            draw(in: CGRect(origin: .zero, size: newSize))
+//        }
+//        
+//        return image
+//    }
+//    
+//    func imageByBestFit(for targetSize: CGSize) -> UIImage {
+//        let aspectRatio = size.width / size.height
+//        let targetHeight = targetSize.height
+//        let scaledWidth = targetSize.height * aspectRatio
+//        
+//        let bestSize = CGSize(width: scaledWidth, height: targetHeight)
+//        return imageWith(newSize: bestSize)
+//    }
+//    
+//}
+//
+//extension Optional where Wrapped == UIImage {
+//    func isSame(photo: UIImage?) -> Bool {
+//        switch (self, photo) {
+//        case (nil, nil):
+//            return true
+//        case (nil, _), (_, nil):
+//            return false
+//        case (let p1, let p2):
+//            return p1!.isEqual(p2)
+//        }
+//    }
+//}
diff --git a/LingQi/LingQi/Tools/Extensions/UIImage+Gif.swift b/LingQi/LingQi/Tools/Extensions/UIImage+Gif.swift
new file mode 100644 (file)
index 0000000..88648f8
--- /dev/null
@@ -0,0 +1,225 @@
+//
+//  UIImage+Gif.swift
+//  HTDevelopTools
+//
+//  Created by 胡庚伟 on 2019/3/8.
+//  Copyright © 2019 Exaleap. All rights reserved.
+//
+
+import UIKit
+import ImageIO
+
+extension UIImageView {
+    
+    public func loadGif(name: String) {
+        DispatchQueue.global().async {
+            let image = UIImage.gif(name: name)
+            DispatchQueue.main.async {
+                self.image = image
+            }
+        }
+    }
+    
+    @available(iOS 9.0, *)
+    public func loadGif(asset: String) {
+        DispatchQueue.global().async {
+            let image = UIImage.gif(asset: asset)
+            DispatchQueue.main.async {
+                self.image = image
+            }
+        }
+    }
+    
+}
+
+extension UIImage {
+    
+    public class func gif(data: Data) -> UIImage? {
+        // Create source from data
+        guard let source = CGImageSourceCreateWithData(data as CFData, nil) else {
+            print("SwiftGif: Source for the image does not exist")
+            return nil
+        }
+        
+        return UIImage.animatedImageWithSource(source)
+    }
+    
+    public class func gif(url: String) -> UIImage? {
+        // Validate URL
+        guard let bundleURL = URL(string: url) else {
+            print("SwiftGif: This image named \"\(url)\" does not exist")
+            return nil
+        }
+        
+        // Validate data
+        guard let imageData = try? Data(contentsOf: bundleURL) else {
+            print("SwiftGif: Cannot turn image named \"\(url)\" into NSData")
+            return nil
+        }
+        
+        return gif(data: imageData)
+    }
+    
+    public class func gif(name: String) -> UIImage? {
+        // Check for existance of gif
+        guard let bundleURL = Bundle.main
+            .url(forResource: name, withExtension: "gif") else {
+                print("SwiftGif: This image named \"\(name)\" does not exist")
+                return nil
+        }
+        
+        // Validate data
+        guard let imageData = try? Data(contentsOf: bundleURL) else {
+            print("SwiftGif: Cannot turn image named \"\(name)\" into NSData")
+            return nil
+        }
+        
+        return gif(data: imageData)
+    }
+    
+    @available(iOS 9.0, *)
+    public class func gif(asset: String) -> UIImage? {
+        // Create source from assets catalog
+        guard let dataAsset = NSDataAsset(name: asset) else {
+            print("SwiftGif: Cannot turn image named \"\(asset)\" into NSDataAsset")
+            return nil
+        }
+        
+        return gif(data: dataAsset.data)
+    }
+    
+    internal class func delayForImageAtIndex(_ index: Int, source: CGImageSource!) -> Double {
+        var delay = 0.1
+        
+        // Get dictionaries
+        let cfProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil)
+        let gifPropertiesPointer = UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: 0)
+        defer {
+            gifPropertiesPointer.deallocate()
+        }
+        if CFDictionaryGetValueIfPresent(cfProperties, Unmanaged.passUnretained(kCGImagePropertyGIFDictionary).toOpaque(), gifPropertiesPointer) == false {
+            return delay
+        }
+        
+        let gifProperties:CFDictionary = unsafeBitCast(gifPropertiesPointer.pointee, to: CFDictionary.self)
+        
+        // Get delay time
+        var delayObject: AnyObject = unsafeBitCast(
+            CFDictionaryGetValue(gifProperties,
+                                 Unmanaged.passUnretained(kCGImagePropertyGIFUnclampedDelayTime).toOpaque()),
+            to: AnyObject.self)
+        if delayObject.doubleValue == 0 {
+            delayObject = unsafeBitCast(CFDictionaryGetValue(gifProperties,
+                                                             Unmanaged.passUnretained(kCGImagePropertyGIFDelayTime).toOpaque()), to: AnyObject.self)
+        }
+        
+        if let delayObject = delayObject as? Double, delayObject > 0 {
+            delay = delayObject
+        } else {
+            delay = 0.1 // Make sure they're not too fast
+        }
+        
+        return delay
+    }
+    
+    internal class func gcdForPair(_ a: Int?, _ b: Int?) -> Int {
+        var a = a
+        var b = b
+        // Check if one of them is nil
+        if b == nil || a == nil {
+            if b != nil {
+                return b!
+            } else if a != nil {
+                return a!
+            } else {
+                return 0
+            }
+        }
+        
+        // Swap for modulo
+        if a! < b! {
+            let c = a
+            a = b
+            b = c
+        }
+        
+        // Get greatest common divisor
+        var rest: Int
+        while true {
+            rest = a! % b!
+            
+            if rest == 0 {
+                return b! // Found it
+            } else {
+                a = b
+                b = rest
+            }
+        }
+    }
+    
+    internal class func gcdForArray(_ array: Array<Int>) -> Int {
+        if array.isEmpty {
+            return 1
+        }
+        
+        var gcd = array[0]
+        
+        for val in array {
+            gcd = UIImage.gcdForPair(val, gcd)
+        }
+        
+        return gcd
+    }
+    
+    internal class func animatedImageWithSource(_ source: CGImageSource) -> UIImage? {
+        let count = CGImageSourceGetCount(source)
+        var images = [CGImage]()
+        var delays = [Int]()
+        
+        // Fill arrays
+        for i in 0..<count {
+            // Add image
+            if let image = CGImageSourceCreateImageAtIndex(source, i, nil) {
+                images.append(image)
+            }
+            
+            // At it's delay in cs
+            let delaySeconds = UIImage.delayForImageAtIndex(Int(i),
+                                                            source: source)
+            delays.append(Int(delaySeconds * 1000.0)) // Seconds to ms
+        }
+        
+        // Calculate full duration
+        let duration: Int = {
+            var sum = 0
+            
+            for val: Int in delays {
+                sum += val
+            }
+            
+            return sum
+        }()
+        
+        // Get frames
+        let gcd = gcdForArray(delays)
+        var frames = [UIImage]()
+        
+        var frame: UIImage
+        var frameCount: Int
+        for i in 0..<count {
+            frame = UIImage(cgImage: images[Int(i)])
+            frameCount = Int(delays[Int(i)] / gcd)
+            
+            for _ in 0..<frameCount {
+                frames.append(frame)
+            }
+        }
+        
+        // Heyhey
+        let animation = UIImage.animatedImage(with: frames,
+                                              duration: Double(duration) / 1000.0)
+        
+        return animation
+    }
+    
+}
diff --git a/LingQi/LingQi/Tools/Extensions/UIImage+ImageEffects.h b/LingQi/LingQi/Tools/Extensions/UIImage+ImageEffects.h
new file mode 100755 (executable)
index 0000000..04d15b1
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+     File: UIImage+ImageEffects.h
+ Abstract: This is a category of UIImage that adds methods to apply blur and tint effects to an image. This is the code you’ll want to look out to find out how to use vImage to efficiently calculate a blur.
+  Version: 1.0
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2013 Apple Inc. All Rights Reserved.
+ 
+ 
+ Copyright © 2013 Apple Inc. All rights reserved.
+ WWDC 2013 License
+ 
+ NOTE: This Apple Software was supplied by Apple as part of a WWDC 2013
+ Session. Please refer to the applicable WWDC 2013 Session for further
+ information.
+ 
+ IMPORTANT: This Apple software is supplied to you by Apple Inc.
+ ("Apple") in consideration of your agreement to the following terms, and
+ your use, installation, modification or redistribution of this Apple
+ software constitutes acceptance of these terms. If you do not agree with
+ these terms, please do not use, install, modify or redistribute this
+ Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a non-exclusive license, under
+ Apple's copyrights in this original Apple software (the "Apple
+ Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES
+ NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
+ IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ EA1002
+ 5/3/2013
+ */
+
+@import UIKit;
+
+@interface UIImage (ImageEffects)
+
+#pragma mark - Blur Image
+
+/**
+ *  Get blured image.
+ *
+ *  @return Blured image.
+ */
+- (UIImage *)blurImage;
+
+/**
+ *  Get the blured image masked by another image.
+ *
+ *  @param maskImage Image used for mask.
+ *
+ *  @return the Blured image.
+ */
+- (UIImage *)blurImageWithMask:(UIImage *)maskImage;
+
+/**
+ *  Get blured image and you can set the blur radius.
+ *
+ *  @param radius Blur radius.
+ *
+ *  @return Blured image.
+ */
+- (UIImage *)blurImageWithRadius:(CGFloat)radius;
+
+/**
+ *  Get blured image at specified frame.
+ *
+ *  @param frame The specified frame that you use to blur.
+ *
+ *  @return Blured image.
+ */
+- (UIImage *)blurImageAtFrame:(CGRect)frame;
+
+#pragma mark - Grayscale Image
+
+/**
+ *  Get grayScale image.
+ *
+ *  @return GrayScaled image.
+ */
+- (UIImage *)grayScale;
+
+#pragma mark - Some Useful Method
+
+/**
+ *  Scale image with fixed width.
+ *
+ *  @param width The fixed width you give.
+ *
+ *  @return Scaled image.
+ */
+- (UIImage *)scaleWithFixedWidth:(CGFloat)width;
+
+/**
+ *  Scale image with fixed height.
+ *
+ *  @param height The fixed height you give.
+ *
+ *  @return Scaled image.
+ */
+- (UIImage *)scaleWithFixedHeight:(CGFloat)height;
+
+/**
+ *  Get the image average color.
+ *
+ *  @return Average color from the image.
+ */
+- (UIColor *)averageColor;
+
+/**
+ *  Get cropped image at specified frame.
+ *
+ *  @param frame The specified frame that you use to crop.
+ *
+ *  @return Cropped image
+ */
+- (UIImage *)croppedImageAtFrame:(CGRect)frame;
+
+@end
diff --git a/LingQi/LingQi/Tools/Extensions/UIImage+ImageEffects.m b/LingQi/LingQi/Tools/Extensions/UIImage+ImageEffects.m
new file mode 100755 (executable)
index 0000000..70b0798
--- /dev/null
@@ -0,0 +1,488 @@
+/*
+     File: UIImage+ImageEffects.m
+ Abstract: This is a category of UIImage that adds methods to apply blur and tint effects to an image. This is the code you’ll want to look out to find out how to use vImage to efficiently calculate a blur.
+  Version: 1.0
+ 
+ Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
+ Inc. ("Apple") in consideration of your agreement to the following
+ terms, and your use, installation, modification or redistribution of
+ this Apple software constitutes acceptance of these terms.  If you do
+ not agree with these terms, please do not use, install, modify or
+ redistribute this Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a personal, non-exclusive
+ license, under Apple's copyrights in this original Apple software (the
+ "Apple Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple.  Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
+ MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
+ THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ Copyright (C) 2013 Apple Inc. All Rights Reserved.
+ 
+ 
+ Copyright © 2013 Apple Inc. All rights reserved.
+ WWDC 2013 License
+ 
+ NOTE: This Apple Software was supplied by Apple as part of a WWDC 2013
+ Session. Please refer to the applicable WWDC 2013 Session for further
+ information.
+ 
+ IMPORTANT: This Apple software is supplied to you by Apple Inc.
+ ("Apple") in consideration of your agreement to the following terms, and
+ your use, installation, modification or redistribution of this Apple
+ software constitutes acceptance of these terms. If you do not agree with
+ these terms, please do not use, install, modify or redistribute this
+ Apple software.
+ 
+ In consideration of your agreement to abide by the following terms, and
+ subject to these terms, Apple grants you a non-exclusive license, under
+ Apple's copyrights in this original Apple software (the "Apple
+ Software"), to use, reproduce, modify and redistribute the Apple
+ Software, with or without modifications, in source and/or binary forms;
+ provided that if you redistribute the Apple Software in its entirety and
+ without modifications, you must retain this notice and the following
+ text and disclaimers in all such redistributions of the Apple Software.
+ Neither the name, trademarks, service marks or logos of Apple Inc. may
+ be used to endorse or promote products derived from the Apple Software
+ without specific prior written permission from Apple. Except as
+ expressly stated in this notice, no other rights or licenses, express or
+ implied, are granted by Apple herein, including but not limited to any
+ patent rights that may be infringed by your derivative works or by other
+ works in which the Apple Software may be incorporated.
+ 
+ The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES
+ NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
+ IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
+ OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
+ 
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
+ MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
+ AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
+ STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ 
+ EA1002
+ 5/3/2013
+ */
+
+#import "UIImage+ImageEffects.h"
+#import <float.h>
+@import Accelerate;
+
+@implementation UIImage (ImageEffects)
+
+
+- (UIImage *)applyLightEffect{
+    
+    UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3];
+    return [self applyBlurWithRadius:30 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
+}
+
+
+- (UIImage *)applyExtraLightEffect {
+    
+    UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82];
+    return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
+}
+
+
+- (UIImage *)applyDarkEffect {
+    
+    UIColor *tintColor = [UIColor colorWithWhite:0.11 alpha:0.73];
+    return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
+}
+
+
+- (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor {
+    
+    const CGFloat EffectColorAlpha = 0.6;
+    UIColor      *effectColor      = tintColor;
+    int           componentCount   = (int)CGColorGetNumberOfComponents(tintColor.CGColor);
+    
+    if (componentCount == 2) {
+        
+        CGFloat b;
+        if ([tintColor getWhite:&b alpha:NULL]) {
+            
+            effectColor = [UIColor colorWithWhite:b alpha:EffectColorAlpha];
+        }
+        
+    } else {
+        
+        CGFloat r, g, b;
+        if ([tintColor getRed:&r green:&g blue:&b alpha:NULL]) {
+            
+            effectColor = [UIColor colorWithRed:r green:g blue:b alpha:EffectColorAlpha];
+        }
+    }
+    
+    return [self applyBlurWithRadius:20 tintColor:effectColor saturationDeltaFactor:1.4 maskImage:nil];
+}
+
+- (UIImage *)blurImage {
+    
+    return [self applyBlurWithRadius:20
+                           tintColor:[UIColor colorWithWhite:0 alpha:0.0]
+               saturationDeltaFactor:1.4
+                           maskImage:nil];
+}
+
+- (UIImage *)blurImageWithRadius:(CGFloat)radius {
+    
+    return [self applyBlurWithRadius:radius
+                           tintColor:[UIColor colorWithWhite:0 alpha:0.0]
+               saturationDeltaFactor:1.4
+                           maskImage:nil];
+}
+
+- (UIImage *)blurImageWithMask:(UIImage *)maskImage {
+    
+    return [self applyBlurWithRadius:20
+                           tintColor:[UIColor colorWithWhite:0 alpha:0.0]
+               saturationDeltaFactor:1.4
+                           maskImage:maskImage];
+}
+
+- (UIImage *)blurImageAtFrame:(CGRect)frame {
+    
+    return [self applyBlurWithRadius:20
+                           tintColor:[UIColor colorWithWhite:0 alpha:0.0]
+               saturationDeltaFactor:1.4
+                           maskImage:nil
+                             atFrame:frame];
+}
+
+- (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage {
+    
+    // Check pre-conditions.
+    if (self.size.width < 1 || self.size.height < 1) {
+        
+        NSLog (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self);
+        return nil;
+    }
+    
+    if (!self.CGImage) {
+        
+        NSLog (@"*** error: image must be backed by a CGImage: %@", self);
+        return nil;
+    }
+    
+    if (maskImage && !maskImage.CGImage) {
+        
+        NSLog (@"*** error: maskImage must be backed by a CGImage: %@", maskImage);
+        return nil;
+    }
+
+    CGRect   imageRect   = { CGPointZero, self.size };
+    UIImage *effectImage = self;
+    
+    BOOL hasBlur             = blurRadius > __FLT_EPSILON__;
+    BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__;
+    if (hasBlur || hasSaturationChange) {
+        
+        UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
+        CGContextRef effectInContext = UIGraphicsGetCurrentContext();
+        CGContextScaleCTM(effectInContext, 1.0, -1.0);
+        CGContextTranslateCTM(effectInContext, 0, -self.size.height);
+        CGContextDrawImage(effectInContext, imageRect, self.CGImage);
+
+        vImage_Buffer effectInBuffer;
+        effectInBuffer.data     = CGBitmapContextGetData(effectInContext);
+        effectInBuffer.width    = CGBitmapContextGetWidth(effectInContext);
+        effectInBuffer.height   = CGBitmapContextGetHeight(effectInContext);
+        effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext);
+    
+        UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
+        CGContextRef effectOutContext = UIGraphicsGetCurrentContext();
+        vImage_Buffer effectOutBuffer;
+        effectOutBuffer.data     = CGBitmapContextGetData(effectOutContext);
+        effectOutBuffer.width    = CGBitmapContextGetWidth(effectOutContext);
+        effectOutBuffer.height   = CGBitmapContextGetHeight(effectOutContext);
+        effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext);
+
+        if (hasBlur) {
+            
+            // A description of how to compute the box kernel width from the Gaussian
+            // radius (aka standard deviation) appears in the SVG spec:
+            // http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement
+            // 
+            // For larger values of 's' (s >= 2.0), an approximation can be used: Three
+            // successive box-blurs build a piece-wise quadratic convolution kernel, which
+            // approximates the Gaussian kernel to within roughly 3%.
+            //
+            // let d = floor(s * 3*sqrt(2*pi)/4 + 0.5)
+            // 
+            // ... if d is odd, use three box-blurs of size 'd', centered on the output pixel.
+            // 
+            CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale];
+            NSUInteger radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5);
+            if (radius % 2 != 1) {
+                
+                radius += 1; // force radius to be odd so that the three box-blur methodology works.
+            }
+            
+            vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, (uint32_t)radius, (uint32_t)radius, 0, kvImageEdgeExtend);
+            vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, (uint32_t)radius, (uint32_t)radius, 0, kvImageEdgeExtend);
+            vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, (uint32_t)radius, (uint32_t)radius, 0, kvImageEdgeExtend);
+        }
+        
+        BOOL effectImageBuffersAreSwapped = NO;
+        if (hasSaturationChange) {
+            
+            CGFloat s = saturationDeltaFactor;
+            CGFloat floatingPointSaturationMatrix[] = {
+                0.0722 + 0.9278 * s,  0.0722 - 0.0722 * s,  0.0722 - 0.0722 * s,  0,
+                0.7152 - 0.7152 * s,  0.7152 + 0.2848 * s,  0.7152 - 0.7152 * s,  0,
+                0.2126 - 0.2126 * s,  0.2126 - 0.2126 * s,  0.2126 + 0.7873 * s,  0,
+                                  0,                    0,                    0,  1,
+            };
+            const int32_t divisor = 256;
+            NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]);
+            int16_t saturationMatrix[matrixSize];
+            
+            for (NSUInteger i = 0; i < matrixSize; ++i) {
+                
+                saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor);
+            }
+            
+            if (hasBlur) {
+                
+                vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
+                effectImageBuffersAreSwapped = YES;
+                
+            } else {
+                
+                vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
+            }
+        }
+        
+        if (!effectImageBuffersAreSwapped) {
+            
+            effectImage = UIGraphicsGetImageFromCurrentImageContext();
+        }
+        
+        UIGraphicsEndImageContext();
+
+        if (effectImageBuffersAreSwapped) {
+            
+            effectImage = UIGraphicsGetImageFromCurrentImageContext();
+        }
+        
+        UIGraphicsEndImageContext();
+    }
+
+    // Set up output context.
+    UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
+    CGContextRef outputContext = UIGraphicsGetCurrentContext();
+    CGContextScaleCTM(outputContext, 1.0, -1.0);
+    CGContextTranslateCTM(outputContext, 0, -self.size.height);
+
+    // Draw base image.
+    CGContextDrawImage(outputContext, imageRect, self.CGImage);
+
+    // Draw effect image.
+    if (hasBlur) {
+        
+        CGContextSaveGState(outputContext);
+        
+        if (maskImage) {
+            
+            CGContextClipToMask(outputContext, imageRect, maskImage.CGImage);
+        }
+        
+        CGContextDrawImage(outputContext, imageRect, effectImage.CGImage);
+        CGContextRestoreGState(outputContext);
+    }
+
+    // Add in color tint.
+    if (tintColor) {
+        
+        CGContextSaveGState(outputContext);
+        CGContextSetFillColorWithColor(outputContext, tintColor.CGColor);
+        CGContextFillRect(outputContext, imageRect);
+        CGContextRestoreGState(outputContext);
+    }
+
+    // Output image is ready.
+    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
+    UIGraphicsEndImageContext();
+
+    return outputImage;
+}
+
+- (UIImage *)grayScale {
+    
+    int width  = self.size.width;
+    int height = self.size.height;
+    
+    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
+    
+    CGContextRef context = CGBitmapContextCreate(nil,
+                                                 width,
+                                                 height,
+                                                 8, // bits per component
+                                                 0,
+                                                 colorSpace,
+                                                 kCGBitmapByteOrderDefault);
+    
+    CGColorSpaceRelease(colorSpace);
+    
+    if (context == NULL) {
+        
+        return nil;
+    }
+    
+    CGContextDrawImage(context,
+                       CGRectMake(0, 0, width, height), self.CGImage);
+    CGImageRef image   = CGBitmapContextCreateImage(context);
+    UIImage *grayImage = [UIImage imageWithCGImage:image];
+    CFRelease(image);
+    CGContextRelease(context);
+    
+    return grayImage;
+}
+
+- (UIImage *)scaleWithFixedWidth:(CGFloat)width {
+    
+    float newHeight = self.size.height * (width / self.size.width);
+    CGSize size     = CGSizeMake(width, newHeight);
+    UIGraphicsBeginImageContextWithOptions(size, NO, 0);
+    
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    
+    CGContextTranslateCTM(context, 0.0, size.height);
+    CGContextScaleCTM(context, 1.0, -1.0);
+    
+    CGContextSetBlendMode(context, kCGBlendModeCopy);
+    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, size.width, size.height), self.CGImage);
+    
+    UIImage *imageOut = UIGraphicsGetImageFromCurrentImageContext();
+    
+    UIGraphicsEndImageContext();
+    
+    return imageOut;
+}
+
+- (UIImage *)scaleWithFixedHeight:(CGFloat)height {
+    
+    float newWidth = self.size.width * (height / self.size.height);
+    CGSize size    = CGSizeMake(newWidth, height);
+    
+    UIGraphicsBeginImageContextWithOptions(size, NO, 0);
+    
+    CGContextRef context = UIGraphicsGetCurrentContext();
+    
+    CGContextTranslateCTM(context, 0.0, size.height);
+    CGContextScaleCTM(context, 1.0, -1.0);
+    
+    CGContextSetBlendMode(context, kCGBlendModeCopy);
+    CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, size.width, size.height), self.CGImage);
+    
+    UIImage *imageOut = UIGraphicsGetImageFromCurrentImageContext();
+    
+    UIGraphicsEndImageContext();
+    
+    return imageOut;
+}
+
+- (UIColor *)averageColor {
+    
+    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+    unsigned char rgba[4];
+    CGContextRef context = CGBitmapContextCreate(rgba, 1, 1, 8, 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
+    
+    CGContextDrawImage(context, CGRectMake(0, 0, 1, 1), self.CGImage);
+    CGColorSpaceRelease(colorSpace);
+    CGContextRelease(context);
+    
+    if(rgba[3] > 0) {
+        CGFloat alpha = ((CGFloat)rgba[3])/255.0;
+        CGFloat multiplier = alpha/255.0;
+        return [UIColor colorWithRed:((CGFloat)rgba[0])*multiplier
+                               green:((CGFloat)rgba[1])*multiplier
+                                blue:((CGFloat)rgba[2])*multiplier
+                               alpha:alpha];
+    }
+    else {
+        return [UIColor colorWithRed:((CGFloat)rgba[0])/255.0
+                               green:((CGFloat)rgba[1])/255.0
+                                blue:((CGFloat)rgba[2])/255.0
+                               alpha:((CGFloat)rgba[3])/255.0];
+    }
+}
+
+- (UIImage *)croppedImageAtFrame:(CGRect)frame {
+    
+    frame = CGRectMake(frame.origin.x * self.scale,
+                       frame.origin.y * self.scale,
+                       frame.size.width * self.scale,
+                       frame.size.height * self.scale);
+    
+    CGImageRef sourceImageRef = [self CGImage];
+    CGImageRef newImageRef    = CGImageCreateWithImageInRect(sourceImageRef, frame);
+    UIImage   *newImage       = [UIImage imageWithCGImage:newImageRef scale:[self scale] orientation:[self imageOrientation]];
+    CGImageRelease(newImageRef);
+    return newImage;
+}
+
+- (UIImage *)addImageToImage:(UIImage *)img atRect:(CGRect)cropRect {
+    
+    CGSize size = CGSizeMake(self.size.width, self.size.height);
+    UIGraphicsBeginImageContextWithOptions(size, NO, self.scale);
+    
+    CGPoint pointImg1 = CGPointMake(0,0);
+    [self drawAtPoint:pointImg1];
+    
+    CGPoint pointImg2 = cropRect.origin;
+    [img drawAtPoint: pointImg2];
+    
+    UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
+    UIGraphicsEndImageContext();
+    
+    return result;
+}
+
+- (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius
+                       tintColor:(UIColor *)tintColor
+           saturationDeltaFactor:(CGFloat)saturationDeltaFactor
+                       maskImage:(UIImage *)maskImage
+                         atFrame:(CGRect)frame
+{
+    UIImage *blurredFrame = \
+    [[self croppedImageAtFrame:frame] applyBlurWithRadius:blurRadius
+                                                tintColor:tintColor
+                                    saturationDeltaFactor:saturationDeltaFactor
+                                                maskImage:maskImage];
+    
+    return [self addImageToImage:blurredFrame atRect:frame];
+}
+
+@end
diff --git a/LingQi/LingQi/Tools/Extensions/UIImageView+Develop.swift b/LingQi/LingQi/Tools/Extensions/UIImageView+Develop.swift
new file mode 100644 (file)
index 0000000..0922029
--- /dev/null
@@ -0,0 +1,27 @@
+//
+//  UIImageView+HTDevelop.swift
+//  rrlWallet
+//
+//  Created by Gordon on 2017/12/27.
+//  Copyright © 2017年 Gordon. All rights reserved.
+//
+
+import UIKit
+
+public extension YCDevelop where Base: UIImageView {
+    
+    /// layer旋转360°
+    ///
+    /// - Parameter duration: 时间(旋转360度需要的时间)
+    /// - Parameter repeatCount: 重复次数
+    /// - Parameter direction: 方向 CW:顺时针, CCW:逆时针
+    func img360Start(duration: TimeInterval, repeatCount: Float = MAXFLOAT, direction: String = "CW") {
+        base.layer.start360Rotate(duration: duration, repeatCount: repeatCount, direction: direction)
+        base.isHidden = false
+    }
+    func img360Stop(hideOnComplete: Bool = true) {
+        base.layer.stopRotate360()
+        base.isHidden = hideOnComplete
+    }
+
+}
diff --git a/LingQi/LingQi/Tools/Extensions/UINavigationBar+Develop.swift b/LingQi/LingQi/Tools/Extensions/UINavigationBar+Develop.swift
new file mode 100644 (file)
index 0000000..a71c315
--- /dev/null
@@ -0,0 +1,22 @@
+//
+//  UINavigationBar+HTDevelop.swift
+//  kemiBear
+//
+//  Created by 李扬 on 2017/4/18.
+//  Copyright © 2017年 李扬. All rights reserved.
+//
+
+import UIKit
+
+public extension YCDevelop where Base: UINavigationBar {
+    
+    func setNavBar(bgColor:UIColor, shadowColor:UIColor) {
+        
+        let shadowImg = UIImage.yc.image(color: shadowColor, size: CGSize.init(width: kScreenWid, height: 1), cornerRadius: 0)
+        let bgImg = UIImage.yc.image(color: bgColor, size: CGSize.init(width: kScreenWid, height: kNavBtm), cornerRadius: 0)
+        base.shadowImage = shadowImg
+        base.setBackgroundImage(bgImg, for: .default)
+        base.barTintColor = bgColor
+    }
+}
+
diff --git a/LingQi/LingQi/Tools/Extensions/UITableView+Header.swift b/LingQi/LingQi/Tools/Extensions/UITableView+Header.swift
new file mode 100644 (file)
index 0000000..80844e6
--- /dev/null
@@ -0,0 +1,29 @@
+//
+//  UITableView+Header.swift
+//  zgjd
+//
+//  Created by apple on 2020/12/8.
+//
+
+import Foundation
+import UIKit
+
+extension UITableView {
+    //set the tableHeaderView so that the required height can be determined, update the header's frame and set it again
+    func setAndLayoutTable(header view: UIView) {
+        self.tableHeaderView = view
+        view.setNeedsLayout()
+        view.layoutIfNeeded()
+        view.frame.size = view.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
+        self.tableHeaderView = view
+    }
+    
+    
+//    func setAndLayoutTable(footer view: UIView) {
+//        self.tableFooterView = view
+//        view.setNeedsLayout()
+//        view.layoutIfNeeded()
+//        view.frame.size = view.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
+//        self.tableFooterView = view
+//    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/UITableView_Extension.swift b/LingQi/LingQi/Tools/Extensions/UITableView_Extension.swift
new file mode 100755 (executable)
index 0000000..e2fe85e
--- /dev/null
@@ -0,0 +1,82 @@
+//
+//  UIKitExtensions.swift
+//  RxDataSources
+//
+//  Created by Segii Shulga on 4/26/16.
+//  Copyright © 2016 kzaher. All rights reserved.
+//
+
+import UIKit
+import class UIKit.UITableViewCell
+import class UIKit.UITableView
+import class UIKit.UIViewController
+import struct Foundation.IndexPath
+
+
+public protocol ReusableView {
+    static var reuseIdentifier: String {get}
+}
+
+extension ReusableView {
+    static public var reuseIdentifier: String {
+        return String(describing: self)
+    }
+}
+
+extension UITableViewCell: ReusableView {
+}
+
+extension UIViewController : ReusableView {
+}
+extension UICollectionViewCell: ReusableView {}
+
+
+// MARK: - tableview extension
+extension UITableView {
+    
+    /// cell 复用
+    ///
+    /// - Parameter indexPath: cell indexPath
+    /// - Returns: cell
+    public func dequeueReusableCell<T: UITableViewCell>(forIndexPath indexPath: IndexPath) -> T /* where T: ReusableView */ {
+        guard let cell = dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as? T else {
+            fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)")
+        }
+        
+        return cell
+    }
+    
+    
+    /// 注册table view cell
+    ///
+    /// - Parameter cell: 需要注册的cell
+    public func register<T: UITableViewCell>(_ cell: T.Type) {
+        
+        register(cell.self, forCellReuseIdentifier: cell.reuseIdentifier)
+    }
+    
+    
+    /// 批量注册cell
+    ///
+    /// - Parameter cells: 需要注册的cell数组
+    public func registers<T: UITableViewCell>(_ cells: [T.Type]) {
+        
+        for cell in cells {
+            register(cell.self)
+        }
+    }
+}
+
+extension UITableView {
+    
+    public func dequeueReusable<T: UITableViewCell>(class cell: T.Type) -> T {
+        guard let aCell = dequeueReusableCell(withIdentifier: cell.reuseIdentifier) as? T else {
+            fatalError("Couldn't find UITableViewCell for \(cell.reuseIdentifier), make sure the cell is registered with table view")
+        }
+        return aCell
+    }
+    
+    public func registerCell<T: UITableViewCell>(nib cell: T.Type) {
+        register(UINib(nibName: cell.reuseIdentifier, bundle: nil), forCellReuseIdentifier: cell.reuseIdentifier)
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/UITextField+Extension.swift b/LingQi/LingQi/Tools/Extensions/UITextField+Extension.swift
new file mode 100644 (file)
index 0000000..7510166
--- /dev/null
@@ -0,0 +1,174 @@
+//
+//  UITextField+Extension.swift
+//  zshSeedOne
+//
+//  Created by ios-spec on 2019/3/18.
+//  Copyright © 2019 zsh. All rights reserved.
+//
+
+#if canImport(UIKit) && !os(watchOS)
+import UIKit
+
+extension UITextField {
+    
+    public func setPlaceholder(text: String, font: UIFont, color: UIColor) {
+        
+        let attributes = [
+            NSAttributedString.Key.foregroundColor: color,
+            NSAttributedString.Key.font : font // Note the !
+        ]
+        attributedPlaceholder = NSAttributedString(string: text, attributes:attributes)
+    }
+}
+
+// MARK: - Enums
+public extension UITextField {
+    
+    /// SwifterSwift: UITextField text type.
+    ///
+    /// - emailAddress: UITextField is used to enter email addresses.
+    /// - password: UITextField is used to enter passwords.
+    /// - generic: UITextField is used to enter generic text.
+    enum TextType {
+        /// UITextField is used to enter email addresses.
+        case emailAddress
+        
+        /// UITextField is used to enter passwords.
+        case password
+        
+        /// UITextField is used to enter generic text.
+        case generic
+    }
+    
+}
+
+// MARK: - Properties
+public extension UITextField {
+    
+    /// SwifterSwift: Set textField for common text types.
+    var textType: TextType {
+        get {
+            if keyboardType == .emailAddress {
+                return .emailAddress
+            } else if isSecureTextEntry {
+                return .password
+            }
+            return .generic
+        }
+        set {
+            switch newValue {
+            case .emailAddress:
+                keyboardType = .emailAddress
+                autocorrectionType = .no
+                autocapitalizationType = .none
+                isSecureTextEntry = false
+                placeholder = "Email Address"
+                
+            case .password:
+                keyboardType = .asciiCapable
+                autocorrectionType = .no
+                autocapitalizationType = .none
+                isSecureTextEntry = true
+                placeholder = "Password"
+                
+            case .generic:
+                isSecureTextEntry = false
+            }
+        }
+    }
+    
+    /// SwifterSwift: Check if text field is empty.
+    var isEmpty: Bool {
+        return text?.isEmpty == true
+    }
+    
+    /// SwifterSwift: Return text with no spaces or new lines in beginning and end.
+    var trimmedText: String? {
+        return text?.trimmingCharacters(in: .whitespacesAndNewlines)
+    }
+    
+    /// SwifterSwift: Check if textFields text is a valid email format.
+    ///
+    ///        textField.text = "john@doe.com"
+    ///        textField.hasValidEmail -> true
+    ///
+    ///        textField.text = "swifterswift"
+    ///        textField.hasValidEmail -> false
+    ///
+    var hasValidEmail: Bool {
+        // http://stackoverflow.com/questions/25471114/how-to-validate-an-e-mail-address-in-swift
+        return text!.range(of: "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}",
+                           options: String.CompareOptions.regularExpression,
+                           range: nil, locale: nil) != nil
+    }
+    
+    /// SwifterSwift: Left view tint color.
+    @IBInspectable var leftViewTintColor: UIColor? {
+        get {
+            guard let iconView = leftView as? UIImageView else { return nil }
+            return iconView.tintColor
+        }
+        set {
+            guard let iconView = leftView as? UIImageView else { return }
+            iconView.image = iconView.image?.withRenderingMode(.alwaysTemplate)
+            iconView.tintColor = newValue
+        }
+    }
+    
+    /// SwifterSwift: Right view tint color.
+    @IBInspectable var rightViewTintColor: UIColor? {
+        get {
+            guard let iconView = rightView as? UIImageView else { return nil }
+            return iconView.tintColor
+        }
+        set {
+            guard let iconView = rightView as? UIImageView else { return }
+            iconView.image = iconView.image?.withRenderingMode(.alwaysTemplate)
+            iconView.tintColor = newValue
+        }
+    }
+    
+}
+
+// MARK: - Methods
+public extension UITextField {
+    
+    /// SwifterSwift: Clear text.
+    func clear() {
+        text = ""
+        attributedText = NSAttributedString(string: "")
+    }
+    
+    /// SwifterSwift: Set placeholder text color.
+    ///
+    /// - Parameter color: placeholder text color.
+    func setPlaceHolderTextColor(_ color: UIColor) {
+        guard let holder = placeholder, !holder.isEmpty else { return }
+        attributedPlaceholder = NSAttributedString(string: holder, attributes: [.foregroundColor: color])
+    }
+    
+    /// SwifterSwift: Add padding to the left of the textfield rect.
+    ///
+    /// - Parameter padding: amount of padding to apply to the left of the textfield rect.
+    func addPaddingLeft(_ padding: CGFloat) {
+        let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: padding, height: frame.height))
+        leftView = paddingView
+        leftViewMode = .always
+    }
+    
+    /// SwifterSwift: Add padding to the left of the textfield rect.
+    ///
+    /// - Parameters:
+    ///   - image: left image
+    ///   - padding: amount of padding between icon and the left of textfield
+    func addPaddingLeftIcon(_ image: UIImage, padding: CGFloat) {
+        let imageView = UIImageView(image: image)
+        imageView.contentMode = .center
+        leftView = imageView
+        leftView?.frame.size = CGSize(width: image.size.width + padding, height: image.size.height)
+        leftViewMode = .always
+    }
+    
+}
+
+#endif
diff --git a/LingQi/LingQi/Tools/Extensions/UIView+Develop.swift b/LingQi/LingQi/Tools/Extensions/UIView+Develop.swift
new file mode 100644 (file)
index 0000000..4bd67f5
--- /dev/null
@@ -0,0 +1,282 @@
+//
+//  UIView+Develop.swift
+//  YCDevTools
+//
+//  Created by Liang ZhenYing on 2020/3/5.
+//  Copyright © 2020 zkys. All rights reserved.
+//
+
+import UIKit
+import SnapKit
+
+public extension YCDevelop where Base: UIView {
+    
+    /// 给layer添加阴影
+    ///
+    /// - Parameter color:  颜色
+    /// - Parameter blur:   blur radius
+    /// - Parameter opacity: 不透明
+    /// - Parameter rect:   shadowPath
+    ///
+    func addShadow(withRect rect: CGRect, color: UIColor, blur: CGFloat, opacity: CGFloat, cornerRadius: CGFloat = 0) {
+        let bLayer = base.layer
+        guard
+            let superV = base.superview,
+            bLayer.masksToBounds else {
+                bLayer.addShadow(withRect: rect, cornerRadius: cornerRadius, color: color, blur: blur, opacity: opacity)
+                return
+        }
+        /// 创建一个背景view
+        let bg = UIView()
+        bg.isUserInteractionEnabled = false
+        bg.backgroundColor = .clear
+        superV.insertSubview(bg, belowSubview: base)
+        bg.layer.addShadow(withRect: rect, cornerRadius: cornerRadius, color: color, blur: blur, opacity: opacity)
+        bg.snp.makeConstraints { (m) in
+            m.edges.equalTo(base)
+        }
+    }
+    
+    func addShadowOffset(color: UIColor, blur: CGFloat, opacity: CGFloat, offset: CGSize) {
+        let bLayer = base.layer
+        guard
+            let superV = base.superview,
+            bLayer.masksToBounds else {
+                bLayer.addShadowOffset(color: color, blur: blur, opacity: opacity, offset: offset)
+                return
+        }
+        /// 创建一个背景view
+        let bg = UIView()
+        bg.isUserInteractionEnabled = false
+        bg.backgroundColor = .clear
+        superV.insertSubview(bg, belowSubview: base)
+        bg.layer.addShadowOffset(color: color, blur: blur, opacity: opacity, offset: offset)
+        bg.snp.makeConstraints { (m) in
+            m.edges.equalTo(base)
+        }
+    }
+    
+    /// 给自己快速添加一个渐变layer
+    ///
+    /// - Parameter colors: 渐变颜色
+    /// - Parameter direction: 渐变方向
+    func addgradientLayer(colors: [UIColor], direction: LYGradientLayerDirectionOption, rect: CGRect = .zero) {
+        var r = rect
+        if r == .zero { r = base.bounds }
+        let gradient = CAGradientLayer.yc.gradientLayerWith(colors: colors, frame: r, direction: direction)
+        if (base.layer.sublayers?.count ?? 0) > 0 {
+            base.layer.insertSublayer(gradient, at: 0)
+        } else {
+            base.layer.addSublayer(gradient)
+        }
+    }
+   
+    /// 设置圆角
+//    func setRoundRect() {
+//        let bLayer = base.layer
+//        bLayer.cornerRadius = base.bounds.size.height * 0.5
+//        bLayer.masksToBounds = true
+//    }
+    
+    /// 设置圆角 半径
+    func setCornerRadius(_ radius:CGFloat) {
+        let bLayer = base.layer
+        bLayer.cornerRadius = radius
+        bLayer.masksToBounds = true
+    }
+    ///  设置指定位置圆角
+    func setCorners(withRoundedRect roundedRect: CGRect,
+                    roundingCorners: UIRectCorner,
+                    cornerRadii: CGSize) {
+        let cornerPath = UIBezierPath(roundedRect: roundedRect,
+                                byRoundingCorners: roundingCorners,
+                                cornerRadii: cornerRadii)
+        let shapeLayer = CAShapeLayer()
+        shapeLayer.frame = base.bounds
+        shapeLayer.path = cornerPath.cgPath
+        base.layer.mask = shapeLayer
+    }
+    /// 设置border
+    func setBorder(width: CGFloat, color: UIColor, radius: CGFloat = 0) {
+        let bLayer = base.layer
+        bLayer.borderColor = color.cgColor
+        bLayer.borderWidth = width
+        if radius > 0 {
+            bLayer.cornerRadius = radius
+        }
+        bLayer.masksToBounds = true
+    }
+    /// layer旋转360°
+    ///
+    /// - Parameter duration: 时间(旋转360度需要的时间)
+    /// - Parameter repeatCount: 重复次数
+    /// - Parameter direction: 方向 CW:顺时针, CCW:逆时针
+    func start360Rotate(duration: TimeInterval, repeatCount: Float = MAXFLOAT, direction: String = "CW") {
+        base.layer.start360Rotate(duration: duration, repeatCount: repeatCount, direction: direction)
+    }
+    func pause360Rotate() {
+        base.layer.pause360Rotate()
+    }
+    func stopRotate360() {
+        base.layer.stopRotate360()
+    }
+    /// scale动画
+    func scaleAnimation(duration: TimeInterval = 0.3, zoomin: Double = 1.03, _ finished: @escaping () -> Void) {
+        let scaleAnimation = CAKeyframeAnimation(keyPath: "transform.scale")
+        scaleAnimation.duration = duration
+        scaleAnimation.values = [1.0, zoomin, 1.0]
+        base.layer.add(scaleAnimation, forKey: nil)
+        DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
+            finished()
+        }
+    }
+   
+    /// 翻转动画
+    func flipAnimate(duration: TimeInterval, halfTimeAnimation: @escaping () -> Void , _ finished: @escaping () -> Void) {
+       
+        let keyAnimation = CAKeyframeAnimation(keyPath: "transform.rotation.y")
+        keyAnimation.values = [0, 0.2.π, 0.35.π, 0.5.π, 0.1.π, -0.07.π, 0]
+        keyAnimation.duration = duration
+        base.layer.add(keyAnimation, forKey: nil)
+        DispatchQueue.main.asyncAfter(deadline: .now() + duration * 0.5) {
+            halfTimeAnimation()
+        }
+        DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
+            finished()
+        }
+    }
+    
+    ///
+    func addBlurEffect(_ style: UIBlurEffect.Style = .light,
+                       rect: CGRect = .zero) {
+        let effect = UIBlurEffect.init(style: style)
+        let gaussianView = UIVisualEffectView.init(effect: effect)
+        var r = rect
+        if r == .zero { r = base.bounds }
+        gaussianView.frame = r
+        base.layer.allowsGroupOpacity = false
+        base.addSubview(gaussianView)
+    }
+    
+
+    // MARK: === 抖动动画
+    func shakeAnimate() {
+        let ani = CABasicAnimation(keyPath: "transform.rotation.z")
+        // 设置运动形式
+        ani.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
+        // 设置开始位置
+        ani.fromValue = -0.08
+        // 设置结束位置
+        ani.toValue = 0.08
+        // 设置自动反转
+        ani.autoreverses = true
+        // 设置时间
+        ani.duration = 0.1
+        // 设置次数
+        ani.repeatCount = 2
+        // 添加上动画
+        base.layer.add(ani, forKey: nil)
+    }
+    
+    
+    // MARK: === spring animate
+    static func spring(animations: @escaping () -> Void) {
+        springAnimate(animations: animations)
+    }
+    // MARK: === spring animate with completion
+    static func cSpring(animations: @escaping () -> Void,
+                        completion: @escaping ((Bool) -> Void)) {
+        springAnimate(animations: animations, completion: completion)
+    }
+    
+    static func springAnimate(withDuration duration: TimeInterval = 0.5,
+                       delay: TimeInterval = 0,
+                       usingSpringWithDamping dampingRatio: CGFloat = 0.7,
+                       initialSpringVelocity velocity: CGFloat = 0.3,
+                       options: UIView.AnimationOptions = [.allowUserInteraction],
+                       animations: @escaping () -> Void,
+                       completion: ((Bool) -> Void)? = nil) {
+        UIView.animate(withDuration: duration,
+                       delay: delay,
+                       usingSpringWithDamping: dampingRatio,
+                       initialSpringVelocity: velocity,
+                       animations: animations,
+                       completion: completion)
+    }
+    
+    // MARK: === snapshot
+    var snapshot: UIImage? {
+        UIGraphicsBeginImageContextWithOptions(base.bounds.size, false, UIScreen.main.scale)
+        defer { UIGraphicsEndImageContext() }
+        
+        guard let currentContext = UIGraphicsGetCurrentContext()
+        else { return nil }
+        base.layer.render(in: currentContext)
+        guard let snapshot = UIGraphicsGetImageFromCurrentImageContext()
+        else { return nil }
+        return snapshot
+    }
+    
+    // MARK: === snapshot
+    var graySnapshot: UIImage? {
+        UIGraphicsBeginImageContextWithOptions(CGSize(width: base.bounds.size.width + 60.fitR, height: base.bounds.size.height + 60.fitR), false, UIScreen.main.scale)
+        defer { UIGraphicsEndImageContext() }
+        
+        guard let currentContext = UIGraphicsGetCurrentContext()
+        else { return nil }
+        currentContext.setFillColor(UIColor.gray.withAlphaComponent(0.1).cgColor)
+        // 填充背景色
+        currentContext.fill(CGRect(x: 0, y: 0, width: base.bounds.size.width + 60.fitR , height: base.bounds.size.height + 60.fitR))
+        
+        guard let image = self.imageWithView(view: base) else {
+            return UIImage()
+        }
+        image.draw(at: CGPoint(x: 30.fitR, y: 30.fitR))
+        guard let snapshot = UIGraphicsGetImageFromCurrentImageContext()
+        else { return nil }
+        return snapshot
+    }
+    
+    func imageWithView(view: UIView) -> UIImage? {
+        UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, UIScreen.main.scale)
+        view.layer.render(in: UIGraphicsGetCurrentContext()!)
+        let snapshotImage = UIGraphicsGetImageFromCurrentImageContext()
+        UIGraphicsEndImageContext()
+        return snapshotImage
+    }
+    func drawDashLine(lineLength : Int ,lineSpacing : Int,lineColor : UIColor){
+         let shapeLayer = CAShapeLayer()
+         shapeLayer.bounds = base.bounds
+ //        只要是CALayer这种类型,他的anchorPoint默认都是(0.5,0.5)
+         shapeLayer.anchorPoint = CGPoint(x: 0, y: 0)
+ //        shapeLayer.fillColor = UIColor.blue.cgColor
+         shapeLayer.strokeColor = lineColor.cgColor
+
+         shapeLayer.lineWidth = base.frame.size.height
+        shapeLayer.lineJoin = .round
+
+         shapeLayer.lineDashPattern = [NSNumber(value: lineLength),NSNumber(value: lineSpacing)]
+
+         let path = CGMutablePath()
+         path.move(to: CGPoint(x: 0, y: 0))
+         path.addLine(to: CGPoint(x: 0 , y: base.frame.size.height))
+
+         shapeLayer.path = path
+        base.layer.addSublayer(shapeLayer)
+     }
+    func removeAllSubViews(){
+        let list = base.subviews
+        for item in list {
+            item.removeFromSuperview()
+        }
+    }
+    func addTap(target:Any?,action:Selector?){
+        let tap = UITapGestureRecognizer(target: target, action: action)
+        base.addGestureRecognizer(tap)
+        base.isUserInteractionEnabled = true
+    }
+}
+
+
+
+
diff --git a/LingQi/LingQi/Tools/Extensions/UIView+Loading.swift b/LingQi/LingQi/Tools/Extensions/UIView+Loading.swift
new file mode 100644 (file)
index 0000000..6045798
--- /dev/null
@@ -0,0 +1,47 @@
+//
+//  UIView+Loading.swift
+//  zgjd
+//
+//  Created by apple on 2021/2/25.
+//
+
+import Foundation
+import UIKit
+
+private var loadingViewkey: Void?
+
+public extension YCDevelop where Base: UIView {
+    fileprivate var loadingView: UIActivityIndicatorView? {
+        return objc_getAssociatedObject(base, &loadingViewkey) as? UIActivityIndicatorView
+    }
+
+    func showLoading() {
+        var indicator:UIActivityIndicatorView
+        if loadingView == nil{
+            indicator = UIActivityIndicatorView()
+            indicator.hidesWhenStopped = true
+            if #available(iOS 13.0, *) {
+                indicator.style = .large
+            } else {
+                indicator.style = .gray
+            }
+            objc_setAssociatedObject(base, &loadingViewkey, indicator, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+        else{
+            indicator = loadingView!
+        }
+        
+        base.addSubview(indicator)
+        base.bringSubviewToFront(indicator)
+        indicator.startAnimating()
+        
+        indicator.snp.makeConstraints { (m) in
+//            m.width.height.equalTo(50.fitR)
+            m.center.equalToSuperview()
+        }
+    }
+    func hiddenLoading(){
+        loadingView?.stopAnimating()
+        loadingView?.removeFromSuperview()
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/UIView+Rect.swift b/LingQi/LingQi/Tools/Extensions/UIView+Rect.swift
new file mode 100644 (file)
index 0000000..38bb992
--- /dev/null
@@ -0,0 +1,109 @@
+//
+//  UIView+Rect.swift
+//  HTDevelop
+//
+//  Created by 李扬 on 2019/1/2.
+//  Copyright © 2019 rrl360. All rights reserved.
+//
+
+import UIKit
+
+public extension UIView {
+    
+    private var x : CGFloat {
+        get { return frame.origin.x }
+        set(newVal) {
+            var tmpFrame : CGRect = frame
+            tmpFrame.origin.x     = newVal
+            frame                 = tmpFrame
+        }
+    }
+    
+    private var y : CGFloat {
+        get { return frame.origin.y }
+        set(newVal) {
+            var tmpFrame : CGRect = frame
+            tmpFrame.origin.y     = newVal
+            frame                 = tmpFrame
+        }
+    }
+    
+    var height : CGFloat {
+        get { return frame.size.height }
+        set(newVal) {
+            var tmpFrame : CGRect = frame
+            tmpFrame.size.height  = newVal
+            frame                 = tmpFrame
+        }
+    }
+    
+    var width : CGFloat {
+        get { return frame.size.width }
+        set(newVal) {
+            var tmpFrame : CGRect = frame
+            tmpFrame.size.width   = newVal
+            frame                 = tmpFrame
+        }
+    }
+    
+    var left : CGFloat {
+        get { return x }
+        set(newVal) { x = newVal }
+    }
+    
+    var right : CGFloat {
+        get { return x + width }
+        set(newVal) { x = newVal - width }
+    }
+    
+    var top : CGFloat {
+        get { return y }
+        set(newVal) { y = newVal }
+    }
+    
+    var bottom : CGFloat {
+        get { return y + height }
+        set(newVal) { y = newVal - height }
+    }
+    var centerX : CGFloat {
+        get { return center.x }
+        set(newVal) {
+            center = CGPoint(x: newVal, y: center.y)
+        }
+    }
+    var centerY : CGFloat {
+        get { return center.y }
+        set(newVal) {
+            center = CGPoint(x: center.x, y: newVal)
+        }
+    }
+    
+    var b_center: CGPoint {
+        get {
+            return CGPoint.init(x: b_centerX, y: b_centerY)
+        }
+    }
+    var b_centerX : CGFloat {
+        get { return width / 2 }
+    }
+    var b_centerY : CGFloat {
+        get { return height / 2 }
+    }
+    var f_origin: CGPoint  {
+        get { return frame.origin }
+        set(newVal) {
+            var rect = self.frame
+            rect.origin = newVal
+            self.frame = rect
+        }
+    }
+    var f_size: CGSize {
+        get { return self.frame.size }
+        set(newVal) {
+            var rect = self.frame
+            rect.size = newVal
+            self.frame = rect
+        }
+    }
+}
+
diff --git a/LingQi/LingQi/Tools/Extensions/UIView+Round.swift b/LingQi/LingQi/Tools/Extensions/UIView+Round.swift
new file mode 100644 (file)
index 0000000..5edf669
--- /dev/null
@@ -0,0 +1,67 @@
+//
+//  UIView+Round.swift
+//  zgjd
+//
+//  Created by apple on 2020/12/9.
+//
+
+import Foundation
+import UIKit
+
+enum RoundType {
+    case top
+    case bottom
+    case all
+    case normal
+    case topWithBottomRight
+}
+
+extension UIView {
+//    func corners(with rect: CGRect, type: RoundType, radius: CGFloat) {
+//        switch type {
+//        case .top:
+//            self.yc.setCorners(withRoundedRect: rect, roundingCorners: [.topLeft,.topRight], cornerRadii: CGSize(width: radius, height: radius))
+//        case .bottom:
+//            self.yc.setCorners(withRoundedRect: rect, roundingCorners: [.bottomLeft,.bottomRight], cornerRadii: CGSize(width: radius, height: radius))
+//        case .all:
+//            self.cornerRadius = radius
+//        case .normal:
+//            self.cornerRadius = 0
+//        }
+//    }
+    
+    func corners(with type: RoundType, radius: CGFloat) {
+        switch type {
+        case .top:
+            corner(with: radius, coners: [.topLeft,.topRight])
+        case .bottom:
+            corner(with: radius, coners: [.bottomLeft,.bottomRight])
+        case .all:
+//            self.n_cornerRadius = radius
+            corner(with: radius, coners: .allCorners)
+        case .normal:
+            self.n_cornerRadius = 0
+        case .topWithBottomRight:
+            corner(with: radius, coners: [.topLeft,.topRight,.bottomRight])
+        }
+    }
+    
+    /// 圆角
+    private func corner(with: CGFloat, coners: UIRectCorner) {
+    
+    guard let sup = self.superview else {
+        print("corner failed, the reason is can't find superview, file - \(#file), line - \(#line)")
+        return
+    }
+    // if use snapkit, need update frame
+    sup.layoutIfNeeded()
+    
+    
+        let maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: coners, cornerRadii: CGSize(width: with, height: with))
+        
+        let maskLayer = CAShapeLayer()
+        maskLayer.frame = self.bounds
+        maskLayer.path = maskPath.cgPath
+        self.layer.mask = maskLayer
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/UIViewExtension.swift b/LingQi/LingQi/Tools/Extensions/UIViewExtension.swift
new file mode 100644 (file)
index 0000000..0ee94dc
--- /dev/null
@@ -0,0 +1,726 @@
+//
+//  UIViewExtension.swift
+//  SNSwiftPackage
+//
+//  Created by Spec on 2019/8/5.
+//  Copyright © 2019 Spec. All rights reserved.
+//
+
+#if canImport(UIKit) && !os(watchOS)
+import UIKit
+
+// MARK: - enums
+public extension UIView {
+    
+    /// SwifterSwift: Shake directions of a view.
+    ///
+    /// - horizontal: Shake left and right.
+    /// - vertical: Shake up and down.
+    enum ShakeDirection {
+        /// Shake left and right.
+        case horizontal
+        
+        /// Shake up and down.
+        case vertical
+    }
+    
+    /// SwifterSwift: Angle units.
+    ///
+    /// - degrees: degrees.
+    /// - radians: radians.
+    enum AngleUnit {
+        /// degrees.
+        case degrees
+        
+        /// radians.
+        case radians
+    }
+    
+    /// SwifterSwift: Shake animations types.
+    ///
+    /// - linear: linear animation.
+    /// - easeIn: easeIn animation.
+    /// - easeOut: easeOut animation.
+    /// - easeInOut: easeInOut animation.
+    enum ShakeAnimationType {
+        /// linear animation.
+        case linear
+        
+        /// easeIn animation.
+        case easeIn
+        
+        /// easeOut animation.
+        case easeOut
+        
+        /// easeInOut animation.
+        case easeInOut
+    }
+    
+}
+
+// MARK: - Properties
+public extension UIView {
+    
+    /// SwifterSwift: Border color of view; also inspectable from Storyboard.
+    @IBInspectable var n_borderColor: UIColor? {
+        get {
+            guard let color = layer.borderColor else { return nil }
+            return UIColor(cgColor: color)
+        }
+        set {
+            guard let color = newValue else {
+                layer.borderColor = nil
+                return
+            }
+            // Fix React-Native conflict issue
+            guard String(describing: type(of: color)) != "__NSCFType" else { return }
+            layer.borderColor = color.cgColor
+        }
+    }
+    
+    /// SwifterSwift: Border width of view; also inspectable from Storyboard.
+    @IBInspectable var n_borderWidth: CGFloat {
+        get {
+            return layer.borderWidth
+        }
+        set {
+            layer.borderWidth = newValue
+        }
+    }
+    
+    /// SwifterSwift: Corner radius of view; also inspectable from Storyboard.
+    @IBInspectable var n_cornerRadius: CGFloat {
+        get {
+            return layer.cornerRadius
+        }
+        set {
+            layer.masksToBounds = true
+            layer.cornerRadius = abs(CGFloat(Int(newValue * 100)) / 100)
+        }
+    }
+    
+    /// SwifterSwift: Height of view.
+//    var height: CGFloat {
+//        get {
+//            return frame.size.height
+//        }
+//        set {
+//            frame.size.height = newValue
+//        }
+//    }
+    
+    /// SwifterSwift: Check if view is in RTL format.
+    var isRightToLeft: Bool {
+        if #available(iOS 10.0, *, tvOS 10.0, *) {
+            return effectiveUserInterfaceLayoutDirection == .rightToLeft
+        } else {
+            return false
+        }
+    }
+    
+    /// SwifterSwift: Take screenshot of view (if applicable).
+    var screenshot: UIImage? {
+        UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, 0)
+        defer {
+            UIGraphicsEndImageContext()
+        }
+        guard let context = UIGraphicsGetCurrentContext() else { return nil }
+        layer.render(in: context)
+        return UIGraphicsGetImageFromCurrentImageContext()
+    }
+    
+    /// SwifterSwift: Shadow color of view; also inspectable from Storyboard.
+    @IBInspectable var shadowColor: UIColor? {
+        get {
+            guard let color = layer.shadowColor else { return nil }
+            return UIColor(cgColor: color)
+        }
+        set {
+            layer.shadowColor = newValue?.cgColor
+        }
+    }
+    
+    /// SwifterSwift: Shadow offset of view; also inspectable from Storyboard.
+    @IBInspectable var shadowOffset: CGSize {
+        get {
+            return layer.shadowOffset
+        }
+        set {
+            layer.shadowOffset = newValue
+        }
+    }
+    
+    /// SwifterSwift: Shadow opacity of view; also inspectable from Storyboard.
+    @IBInspectable var shadowOpacity: Float {
+        get {
+            return layer.shadowOpacity
+        }
+        set {
+            layer.shadowOpacity = newValue
+        }
+    }
+    
+    /// SwifterSwift: Shadow radius of view; also inspectable from Storyboard.
+    @IBInspectable var shadowRadius: CGFloat {
+        get {
+            return layer.shadowRadius
+        }
+        set {
+            layer.shadowRadius = newValue
+        }
+    }
+    
+    /// SwifterSwift: Size of view.
+    var size: CGSize {
+        get {
+            return frame.size
+        }
+        set {
+            width = newValue.width
+            height = newValue.height
+        }
+    }
+    
+    /// SwifterSwift: Get view's parent view controller
+    var parentViewController: UIViewController? {
+        weak var parentResponder: UIResponder? = self
+        while parentResponder != nil {
+            parentResponder = parentResponder!.next
+            if let viewController = parentResponder as? UIViewController {
+                return viewController
+            }
+        }
+        return nil
+    }
+    
+    /// SwifterSwift: Width of view.
+//    var width: CGFloat {
+//        get {
+//            return frame.size.width
+//        }
+//        set {
+//            frame.size.width = newValue
+//        }
+//    }
+    
+    /// SwifterSwift: x origin of view.
+    // swiftlint:disable:next identifier_name
+//    var x: CGFloat {
+//        get {
+//            return frame.origin.x
+//        }
+//        set {
+//            frame.origin.x = newValue
+//        }
+//    }
+    
+    /// SwifterSwift: y origin of view.
+    // swiftlint:disable:next identifier_name
+//    var y: CGFloat {
+//        get {
+//            return frame.origin.y
+//        }
+//        set {
+//            frame.origin.y = newValue
+//        }
+//    }
+    
+}
+
+// MARK: - Methods
+public extension UIView {
+    
+    /// SwifterSwift: Recursively find the first responder.
+    func firstResponder() -> UIView? {
+        var views = [UIView](arrayLiteral: self)
+        var index = 0
+        repeat {
+            let view = views[index]
+            if view.isFirstResponder {
+                return view
+            }
+            views.append(contentsOf: view.subviews)
+            index += 1
+        } while index < views.count
+        return nil
+    }
+    
+    /// SwifterSwift: Set some or all corners radiuses of view.
+    ///
+    /// - Parameters:
+    ///   - corners: array of corners to change (example: [.bottomLeft, .topRight]).
+    ///   - radius: radius for selected corners.
+    func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
+        let maskPath = UIBezierPath(
+            roundedRect: bounds,
+            byRoundingCorners: corners,
+            cornerRadii: CGSize(width: radius, height: radius))
+        
+        let shape = CAShapeLayer()
+        shape.path = maskPath.cgPath
+        layer.mask = shape
+    }
+    
+    /// SwifterSwift: Add shadow to view.
+    ///
+    /// - Parameters:
+    ///   - color: shadow color (default is #137992).
+    ///   - radius: shadow radius (default is 3).
+    ///   - offset: shadow offset (default is .zero).
+    ///   - opacity: shadow opacity (default is 0.5).
+    func addShadow(ofColor color: UIColor = UIColor(red: 0.07, green: 0.47, blue: 0.57, alpha: 1.0), radius: CGFloat = 3, offset: CGSize = .zero, opacity: Float = 0.5) {
+        layer.shadowColor = color.cgColor
+        layer.shadowOffset = offset
+        layer.shadowRadius = radius
+        layer.shadowOpacity = opacity
+        layer.masksToBounds = false
+    }
+    
+    /// SwifterSwift: Add array of subviews to view.
+    ///
+    /// - Parameter subviews: array of subviews to add to self.
+    func addSubviews(_ subviews: [UIView]) {
+        subviews.forEach { addSubview($0) }
+    }
+    
+    /// SwifterSwift: Fade in view.
+    ///
+    /// - Parameters:
+    ///   - duration: animation duration in seconds (default is 1 second).
+    ///   - completion: optional completion handler to run with animation finishes (default is nil)
+    func fadeIn(duration: TimeInterval = 1, completion: ((Bool) -> Void)? = nil) {
+        if isHidden {
+            isHidden = false
+        }
+        UIView.animate(withDuration: duration, animations: {
+            self.alpha = 1
+        }, completion: completion)
+    }
+    
+    /// SwifterSwift: Fade out view.
+    ///
+    /// - Parameters:
+    ///   - duration: animation duration in seconds (default is 1 second).
+    ///   - completion: optional completion handler to run with animation finishes (default is nil)
+    func fadeOut(duration: TimeInterval = 1, completion: ((Bool) -> Void)? = nil) {
+        if isHidden {
+            isHidden = false
+        }
+        UIView.animate(withDuration: duration, animations: {
+            self.alpha = 0
+        }, completion: completion)
+    }
+    
+    /// SwifterSwift: Load view from nib.
+    ///
+    /// - Parameters:
+    ///   - name: nib name.
+    ///   - bundle: bundle of nib (default is nil).
+    /// - Returns: optional UIView (if applicable).
+    class func loadFromNib(named name: String, bundle: Bundle? = nil) -> UIView? {
+        return UINib(nibName: name, bundle: bundle).instantiate(withOwner: nil, options: nil)[0] as? UIView
+    }
+    
+    /// SwifterSwift: Remove all subviews in view.
+    func removeSubviews() {
+        subviews.forEach({ $0.removeFromSuperview() })
+    }
+    
+    /// SwifterSwift: Remove all gesture recognizers from view.
+    func removeGestureRecognizers() {
+        gestureRecognizers?.forEach(removeGestureRecognizer)
+    }
+    
+    /// SwifterSwift: Attaches gesture recognizers to the view.
+    ///
+    /// Attaching gesture recognizers to a view defines the scope of the represented
+    /// gesture, causing it to receive touches hit-tested to that view and all of its
+    /// subviews. The view establishes a strong reference to the gesture recognizers.
+    ///
+    /// - Parameter gestureRecognizers: The array of gesture recognizers to be added to the view.
+    func addGestureRecognizers(_ gestureRecognizers: [UIGestureRecognizer]) {
+        for recognizer in gestureRecognizers {
+            addGestureRecognizer(recognizer)
+        }
+    }
+    
+    /// SwifterSwift: Detaches gesture recognizers from the receiving view.
+    ///
+    /// This method releases gestureRecognizers in addition to detaching them from the view.
+    ///
+    /// - Parameter gestureRecognizers: The array of gesture recognizers to be removed from the view.
+    func removeGestureRecognizers(_ gestureRecognizers: [UIGestureRecognizer]) {
+        for recognizer in gestureRecognizers {
+            removeGestureRecognizer(recognizer)
+        }
+    }
+    
+    /// SwifterSwift: Rotate view by angle on relative axis.
+    ///
+    /// - Parameters:
+    ///   - angle: angle to rotate view by.
+    ///   - type: type of the rotation angle.
+    ///   - animated: set true to animate rotation (default is true).
+    ///   - duration: animation duration in seconds (default is 1 second).
+    ///   - completion: optional completion handler to run with animation finishes (default is nil).
+    func rotate(byAngle angle: CGFloat, ofType type: AngleUnit, animated: Bool = false, duration: TimeInterval = 1, completion: ((Bool) -> Void)? = nil) {
+        let angleWithType = (type == .degrees) ? .pi * angle / 180.0 : angle
+        let aDuration = animated ? duration : 0
+        UIView.animate(withDuration: aDuration, delay: 0, options: .curveLinear, animations: { () -> Void in
+            self.transform = self.transform.rotated(by: angleWithType)
+        }, completion: completion)
+    }
+    
+    /// SwifterSwift: Rotate view to angle on fixed axis.
+    ///
+    /// - Parameters:
+    ///   - angle: angle to rotate view to.
+    ///   - type: type of the rotation angle.
+    ///   - animated: set true to animate rotation (default is false).
+    ///   - duration: animation duration in seconds (default is 1 second).
+    ///   - completion: optional completion handler to run with animation finishes (default is nil).
+    func rotate(toAngle angle: CGFloat, ofType type: AngleUnit, animated: Bool = false, duration: TimeInterval = 1, completion: ((Bool) -> Void)? = nil) {
+        let angleWithType = (type == .degrees) ? .pi * angle / 180.0 : angle
+        let aDuration = animated ? duration : 0
+        UIView.animate(withDuration: aDuration, animations: {
+            self.transform = self.transform.concatenating(CGAffineTransform(rotationAngle: angleWithType))
+        }, completion: completion)
+    }
+    
+    /// SwifterSwift: Scale view by offset.
+    ///
+    /// - Parameters:
+    ///   - offset: scale offset
+    ///   - animated: set true to animate scaling (default is false).
+    ///   - duration: animation duration in seconds (default is 1 second).
+    ///   - completion: optional completion handler to run with animation finishes (default is nil).
+    func scale(by offset: CGPoint, animated: Bool = false, duration: TimeInterval = 1, completion: ((Bool) -> Void)? = nil) {
+        if animated {
+            UIView.animate(withDuration: duration, delay: 0, options: .curveLinear, animations: { () -> Void in
+                self.transform = self.transform.scaledBy(x: offset.x, y: offset.y)
+            }, completion: completion)
+        } else {
+            transform = transform.scaledBy(x: offset.x, y: offset.y)
+            completion?(true)
+        }
+    }
+    
+    /// SwifterSwift: Shake view.
+    ///
+    /// - Parameters:
+    ///   - direction: shake direction (horizontal or vertical), (default is .horizontal)
+    ///   - duration: animation duration in seconds (default is 1 second).
+    ///   - animationType: shake animation type (default is .easeOut).
+    ///   - completion: optional completion handler to run with animation finishes (default is nil).
+    func shake(direction: ShakeDirection = .horizontal, duration: TimeInterval = 1, animationType: ShakeAnimationType = .easeOut, completion:(() -> Void)? = nil) {
+        CATransaction.begin()
+        let animation: CAKeyframeAnimation
+        switch direction {
+        case .horizontal:
+            animation = CAKeyframeAnimation(keyPath: "transform.translation.x")
+        case .vertical:
+            animation = CAKeyframeAnimation(keyPath: "transform.translation.y")
+        }
+        switch animationType {
+        case .linear:
+            animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
+        case .easeIn:
+            animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeIn)
+        case .easeOut:
+            animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
+        case .easeInOut:
+            animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
+        }
+        CATransaction.setCompletionBlock(completion)
+        animation.duration = duration
+        animation.values = [-20.0, 20.0, -20.0, 20.0, -10.0, 10.0, -5.0, 5.0, 0.0 ]
+        layer.add(animation, forKey: "shake")
+        CATransaction.commit()
+    }
+    
+    /// SwifterSwift: Add Visual Format constraints.
+    ///
+    /// - Parameters:
+    ///   - withFormat: visual Format language
+    ///   - views: array of views which will be accessed starting with index 0 (example: [v0], [v1], [v2]..)
+    @available(iOS 9, *) func addConstraints(withFormat: String, views: UIView...) {
+        // https://videos.letsbuildthatapp.com/
+        var viewsDictionary: [String: UIView] = [:]
+        for (index, view) in views.enumerated() {
+            let key = "v\(index)"
+            view.translatesAutoresizingMaskIntoConstraints = false
+            viewsDictionary[key] = view
+        }
+        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: withFormat, options: NSLayoutConstraint.FormatOptions(), metrics: nil, views: viewsDictionary))
+    }
+    
+    /// SwifterSwift: Anchor all sides of the view into it's superview.
+    @available(iOS 9, *)
+    func fillToSuperview() {
+        // https://videos.letsbuildthatapp.com/
+        translatesAutoresizingMaskIntoConstraints = false
+        if let superview = superview {
+            let left = leftAnchor.constraint(equalTo: superview.leftAnchor)
+            let right = rightAnchor.constraint(equalTo: superview.rightAnchor)
+            let top = topAnchor.constraint(equalTo: superview.topAnchor)
+            let bottom = bottomAnchor.constraint(equalTo: superview.bottomAnchor)
+            NSLayoutConstraint.activate([left, right, top, bottom])
+        }
+    }
+    
+    /// SwifterSwift: Add anchors from any side of the current view into the specified anchors and returns the newly added constraints.
+    ///
+    /// - Parameters:
+    ///   - top: current view's top anchor will be anchored into the specified anchor
+    ///   - left: current view's left anchor will be anchored into the specified anchor
+    ///   - bottom: current view's bottom anchor will be anchored into the specified anchor
+    ///   - right: current view's right anchor will be anchored into the specified anchor
+    ///   - topConstant: current view's top anchor margin
+    ///   - leftConstant: current view's left anchor margin
+    ///   - bottomConstant: current view's bottom anchor margin
+    ///   - rightConstant: current view's right anchor margin
+    ///   - widthConstant: current view's width
+    ///   - heightConstant: current view's height
+    /// - Returns: array of newly added constraints (if applicable).
+    @available(iOS 9, *)
+    @discardableResult
+    func anchor(
+        top: NSLayoutYAxisAnchor? = nil,
+        left: NSLayoutXAxisAnchor? = nil,
+        bottom: NSLayoutYAxisAnchor? = nil,
+        right: NSLayoutXAxisAnchor? = nil,
+        topConstant: CGFloat = 0,
+        leftConstant: CGFloat = 0,
+        bottomConstant: CGFloat = 0,
+        rightConstant: CGFloat = 0,
+        widthConstant: CGFloat = 0,
+        heightConstant: CGFloat = 0) -> [NSLayoutConstraint] {
+        // https://videos.letsbuildthatapp.com/
+        translatesAutoresizingMaskIntoConstraints = false
+        
+        var anchors = [NSLayoutConstraint]()
+        
+        if let top = top {
+            anchors.append(topAnchor.constraint(equalTo: top, constant: topConstant))
+        }
+        
+        if let left = left {
+            anchors.append(leftAnchor.constraint(equalTo: left, constant: leftConstant))
+        }
+        
+        if let bottom = bottom {
+            anchors.append(bottomAnchor.constraint(equalTo: bottom, constant: -bottomConstant))
+        }
+        
+        if let right = right {
+            anchors.append(rightAnchor.constraint(equalTo: right, constant: -rightConstant))
+        }
+        
+        if widthConstant > 0 {
+            anchors.append(widthAnchor.constraint(equalToConstant: widthConstant))
+        }
+        
+        if heightConstant > 0 {
+            anchors.append(heightAnchor.constraint(equalToConstant: heightConstant))
+        }
+        
+        anchors.forEach({$0.isActive = true})
+        
+        return anchors
+    }
+    
+    /// SwifterSwift: Anchor center X into current view's superview with a constant margin value.
+    ///
+    /// - Parameter constant: constant of the anchor constraint (default is 0).
+    @available(iOS 9, *)
+    func anchorCenterXToSuperview(constant: CGFloat = 0) {
+        // https://videos.letsbuildthatapp.com/
+        translatesAutoresizingMaskIntoConstraints = false
+        if let anchor = superview?.centerXAnchor {
+            centerXAnchor.constraint(equalTo: anchor, constant: constant).isActive = true
+        }
+    }
+    
+    /// SwifterSwift: Anchor center Y into current view's superview with a constant margin value.
+    ///
+    /// - Parameter withConstant: constant of the anchor constraint (default is 0).
+    @available(iOS 9, *)
+    func anchorCenterYToSuperview(constant: CGFloat = 0) {
+        // https://videos.letsbuildthatapp.com/
+        translatesAutoresizingMaskIntoConstraints = false
+        if let anchor = superview?.centerYAnchor {
+            centerYAnchor.constraint(equalTo: anchor, constant: constant).isActive = true
+        }
+    }
+    
+    /// SwifterSwift: Anchor center X and Y into current view's superview
+    @available(iOS 9, *)
+    func anchorCenterSuperview() {
+        // https://videos.letsbuildthatapp.com/
+        anchorCenterXToSuperview()
+        anchorCenterYToSuperview()
+    }
+    
+    /// SwifterSwift: Search all superviews until a view with the condition is found.
+    ///
+    /// - Parameter predicate: predicate to evaluate on superviews.
+    func ancestorView(where predicate: (UIView?) -> Bool) -> UIView? {
+        if predicate(superview) {
+            return superview
+        }
+        return superview?.ancestorView(where: predicate)
+    }
+    
+    /// SwifterSwift: Search all superviews until a view with this class is found.
+    ///
+    /// - Parameter name: class of the view to search.
+    func ancestorView<T: UIView>(withClass name: T.Type) -> T? {
+        return ancestorView(where: { $0 is T }) as? T
+    }
+    
+}
+
+#endif
+
+
+extension UIView {
+
+    /// 画虚线,调用之前请确保能获取到frame
+    /// 如果有多个calayer在当前空间 会使其他layer失效
+    /// - Parameters:
+    ///   - lineLength: 每一节线长
+    ///   - lineSpacing: 间距
+    ///   - lineColor: 颜色
+    ///   - isHorizontal: 是否水平
+    public func drawDashLine(lineLength: Int, lineSpacing: Int, lineColor: UIColor, isHorizontal: Bool = true) {
+
+        if let sublayers = self.layer.sublayers {
+            for sublayer in sublayers {
+                sublayer.removeFromSuperlayer()
+            }
+
+        }
+        //        self.layer.sublayers = nil
+
+        let shapeLayer = CAShapeLayer()
+        shapeLayer.bounds = self.bounds
+        //        只要是CALayer这种类型,他的anchorPoint默认都是(0.5,0.5)
+        shapeLayer.anchorPoint = CGPoint(x: 0, y: 0)
+        //        shapeLayer.fillColor = UIColor.blue.cgColor
+        shapeLayer.strokeColor = lineColor.cgColor
+
+        //        shapeLayer.lineWidth = self.frame.size.height
+        //        shapeLayer.lineJoin = CAShapeLayerLineJoin.round
+
+        shapeLayer.lineDashPattern = [NSNumber(value: lineLength), NSNumber(value: lineSpacing)]
+
+        let path = CGMutablePath()
+        path.move(to: CGPoint(x: 0, y: 0))
+        if isHorizontal {
+            path.addLine(to: CGPoint(x: self.frame.size.width, y: 0))
+        } else {
+            path.addLine(to: CGPoint(x: 0, y: self.frame.size.height))
+        }
+        shapeLayer.path = path
+        self.layer.addSublayer(shapeLayer)
+    }
+
+    
+    func drawDashBorder(length: CGFloat, width: CGFloat, spacing: CGFloat, color: UIColor) {
+        guard frame != .zero else { return }
+        
+        let topLine = CAShapeLayer()
+        let leftLine = CAShapeLayer()
+        let rightLine = CAShapeLayer()
+        let bottomLine = CAShapeLayer()
+        
+        topLine.bounds = CGRect(x: 0, y: 0, width: frame.width, height: width)
+        leftLine.bounds = CGRect(x: 0, y: 0, width: width, height: frame.height)
+        rightLine.bounds = CGRect(x: 0, y: 0, width: width, height: frame.height)
+        bottomLine.bounds = CGRect(x: 0, y: 0, width: frame.width, height: width)
+    }
+    
+    func drawBoardBottedLine(width: CGFloat, length: CGFloat, space: CGFloat, radius: CGFloat, color: UIColor) {
+        layer.cornerRadius = radius
+        let borderLayer = CAShapeLayer()
+        borderLayer.bounds = bounds
+        
+        borderLayer.position = CGPoint(x: bounds.midX , y: bounds.midY)
+        borderLayer.path = UIBezierPath(roundedRect: borderLayer.bounds, cornerRadius: radius).cgPath
+        borderLayer.lineWidth = width / UIScreen.main.scale
+        
+        borderLayer.lineDashPattern = [length, space] as [NSNumber]
+        borderLayer.lineDashPhase = 0.1
+        
+        borderLayer.fillColor = UIColor.clear.cgColor
+        borderLayer.strokeColor = color.cgColor
+        
+        layer.addSublayer(borderLayer)
+        
+    }
+}
+
+extension UIView {
+    
+    public func shadow(color: UIColor, offset: CGSize, opacity: Float, radius: CGFloat) {
+        layer.shadowColor = color.cgColor
+        layer.shadowOffset = offset
+        layer.shadowOpacity = opacity
+        layer.shadowRadius = radius
+        layer.masksToBounds = false
+//        layer.cornerRadius = radius
+    }
+}
+
+extension UIView {
+    
+    /// 试图 缩放动画
+    /// - Parameter scaleMax: 放大比例  原始1
+    /// - Parameter scaleMin: 缩小比例  原始1
+    /// - Parameter count: 缩放次数
+    public func zoom(scaleMax: CGFloat, scaleMin: CGFloat, count: Int) {
+        
+        let maxTrans = CGAffineTransform(scaleX: scaleMax, y: scaleMax)
+        let minTrans = CGAffineTransform(scaleX: scaleMin, y: scaleMin)
+        
+        self.transform = minTrans
+        
+        zoomAnimation(minTrans: minTrans, maxTrans: maxTrans, maxCount: count)
+    }
+    
+    private func zoomAnimation(minTrans: CGAffineTransform, maxTrans: CGAffineTransform, maxCount: Int, currentCount: Int = 1) {
+        
+        let animtionDuration: TimeInterval = 0.6
+        let completionDuration: TimeInterval = 0.3
+        
+        UIView.animate(withDuration: animtionDuration, animations: {
+            self.transform = maxTrans
+        }, completion: { result in
+            UIView.animate(withDuration: animtionDuration, animations: {
+                self.transform = minTrans
+            }, completion: { result in
+                let newCurrent = currentCount + 1
+                if newCurrent <= maxCount {
+                    self.zoomAnimation(minTrans: minTrans, maxTrans: maxTrans, maxCount: maxCount, currentCount: newCurrent)
+                } else {
+                    UIView.animate(withDuration: completionDuration, animations: {
+                        self.transform = CGAffineTransform(scaleX: 1, y: 1)
+                    })
+                }
+            })
+        })
+    }
+    
+}
+
+
+extension UIView{
+    func rotate() {
+        let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
+        rotation.toValue = NSNumber(value: Double.pi * 2)
+        rotation.duration = 1
+        rotation.isCumulative = true
+        rotation.repeatCount = Float.greatestFiniteMagnitude
+        self.layer.add(rotation, forKey: "rotationAnimation")
+    }
+}
diff --git a/LingQi/LingQi/Tools/Extensions/YCDevelop.swift b/LingQi/LingQi/Tools/Extensions/YCDevelop.swift
new file mode 100644 (file)
index 0000000..efe1504
--- /dev/null
@@ -0,0 +1,51 @@
+//
+//  YCDevelop.swift
+//  YCDevTools
+//
+//  Created by Liang ZhenYing on 2020/3/5.
+//  Copyright © 2020 zkys. All rights reserved.
+//
+
+import UIKit
+import UserNotifications
+
+public final class YCDevelop<Base> {
+    public let base: Base
+    public init(_ base: Base) {
+        self.base = base
+    }
+}
+
+public protocol YCDevelopCompatible {
+    associatedtype YCDevelopType
+    var yc: YCDevelop<YCDevelopType> { get }
+    static var yc: YCDevelop<YCDevelopType>.Type { get }
+}
+
+extension YCDevelopCompatible {
+    public var yc: YCDevelop<Self> {
+        get { return YCDevelop(self) }
+    }
+    public static var yc: YCDevelop<Self>.Type {
+        get { return YCDevelop<Self>.self }
+    }
+}
+
+extension String:           YCDevelopCompatible { }
+extension CALayer:          YCDevelopCompatible { }
+extension TimeInterval:     YCDevelopCompatible { }
+extension Int:              YCDevelopCompatible { }
+extension UIImage:          YCDevelopCompatible { }
+extension UIView:           YCDevelopCompatible { }
+extension FileManager:      YCDevelopCompatible { }
+extension UIColor:          YCDevelopCompatible { }
+extension UIBarButtonItem:  YCDevelopCompatible { }
+extension UIApplication:    YCDevelopCompatible { }
+extension Dictionary:       YCDevelopCompatible { }
+extension CGSize:           YCDevelopCompatible { }
+extension CGRect:           YCDevelopCompatible { }
+extension Date:             YCDevelopCompatible { }
+extension Array:            YCDevelopCompatible { }
+extension UIViewController: YCDevelopCompatible { }
+extension NSAttributedString: YCDevelopCompatible { }
+extension UNUserNotificationCenter: YCDevelopCompatible { }
diff --git a/LingQi/LingQi/Tools/Extensions/zhString.swift b/LingQi/LingQi/Tools/Extensions/zhString.swift
new file mode 100644 (file)
index 0000000..dbb19cd
--- /dev/null
@@ -0,0 +1,52 @@
+//
+//  zhString.swift
+//  kjxq
+//
+//  Created by Spec on 2021/1/5.
+//
+
+import Foundation
+
+extension String {
+    func isIncludeChinese() -> Bool {
+        for ch in self.unicodeScalars {
+            // 中文字符范围:0x4e00 ~ 0x9fff
+            if (0x4e00 < ch.value  && ch.value < 0x9fff) {
+                return true
+            }
+        }
+        return false
+    }
+    func transformToPinyin() -> String {
+        let stringRef = NSMutableString(string: self) as CFMutableString
+        // 转换为带音标的拼音
+        CFStringTransform(stringRef,nil, kCFStringTransformToLatin, false);
+        // 去掉音标
+        CFStringTransform(stringRef, nil, kCFStringTransformStripCombiningMarks, false);
+        let pinyin = stringRef as String;
+     
+        return pinyin
+    }
+    func transformToPinyinWithoutBlank() -> String {
+        var pinyin = self.transformToPinyin()
+        // 去掉空格
+//        pinyin = pinyin.stringByReplacingOccurrencesOfString(" ", withString: "")
+//        pinyin = pinyin.trimmed
+        pinyin = String(pinyin.filter { !" \n\t\r".contains($0) })
+        return pinyin
+    }
+    func getPinyinHead() -> String {
+        // 字符串转换为首字母大写
+        let pinyin = self.transformToPinyinWithoutBlank().capitalized//.capitalizedString
+        var headPinyinStr = ""
+     
+        // 获取所有大写字母
+        for ch in pinyin {
+            if ch <= "Z" && ch >= "A" {
+                headPinyinStr.append(ch)
+            }
+        }
+        return headPinyinStr
+    }
+
+}
diff --git a/LingQi/LingQi/Tools/LogManager.swift b/LingQi/LingQi/Tools/LogManager.swift
new file mode 100644 (file)
index 0000000..c03cc1b
--- /dev/null
@@ -0,0 +1,59 @@
+//
+//  LogManager.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/3.
+//
+
+import Foundation
+import UIKit
+
+class LogManager:NSObject{
+    
+    static let instance = LogManager()
+    
+    var log = "start..."
+    
+    
+    func add(_ text:String){
+        let conent = currentTime() + " ~ " + text
+        print(conent)
+        log += conent + "\n"
+    }
+    
+    func saveToFile(){
+        let document = NSHomeDirectory() + "/Documents/"
+        let fileName = currentTime() + ".txt"
+        let path = document + fileName
+        let urlPath = URL(fileURLWithPath: path)
+        
+        do{
+            try log.write(to: urlPath, atomically: true, encoding: .utf8)
+            print("保存成功")
+            saveFile(filePath: path)
+        }catch{
+            print("保存失败!!!!!!!")
+        }
+    }
+    
+    func currentTime()->String{
+        let dateformatter = DateFormatter()
+        dateformatter.dateFormat = "YYYY-MM-dd HH:mm:ss S"// 自定义时间格式
+        let time = dateformatter.string(from: Date())
+        return time
+    }
+}
+
+extension LogManager:UIDocumentPickerDelegate{
+    //保存文件到手机文件指定目录
+    func saveFile(filePath:String) {
+        let fUrl = NSURL(fileURLWithPath: filePath)
+        let vc = UIDocumentPickerViewController(url: fUrl as URL, in: .exportToService);
+        vc.delegate = self
+        vc.modalPresentationStyle = .overFullScreen
+        UIApplication.shared.keyWindow?.rootViewController?.present(vc, animated: true)
+    }
+    public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
+        controller.dismiss(animated: true)
+    }
+}
diff --git a/LingQi/LingQi/Tools/Logs.swift b/LingQi/LingQi/Tools/Logs.swift
new file mode 100644 (file)
index 0000000..6094025
--- /dev/null
@@ -0,0 +1,19 @@
+//
+//  Logs.swift
+//  Syntax-SNSwfitPackage
+//
+//  Created by zyt on 2018/12/20.
+//  Copyright © 2018 zsh. All rights reserved.
+//
+
+import Foundation
+
+
+public func SNLog<T>(_ message: T, file: String = #file, function: String = #function, line: Int = #line) {
+    #if DEBUG
+    var fileName = file as NSString
+    
+    fileName = fileName.lastPathComponent as NSString
+    print("[\(Date().timeIntervalSince1970) \(fileName)--\(function)--\(line) : \(message)]")
+    #endif
+}
diff --git a/LingQi/LingQi/Tools/NumberToTime.swift b/LingQi/LingQi/Tools/NumberToTime.swift
new file mode 100644 (file)
index 0000000..dca3ae6
--- /dev/null
@@ -0,0 +1,55 @@
+//
+//  NumberToTime.swift
+//  HTDevelop
+//
+//  Created by 李扬 on 2019/1/3.
+//  Copyright © 2019 rrl360. All rights reserved.
+//
+
+import UIKit
+
+public protocol NumerToTime {
+    var num: TimeInterval { get }
+    
+    var millisecond: TimeInterval  { get }
+    var milliseconds: TimeInterval { get }
+    var ms: TimeInterval           { get }
+    
+    var second: TimeInterval       { get }
+    var seconds: TimeInterval      { get }
+    
+    var minute: TimeInterval       { get }
+    var minutes: TimeInterval      { get }
+    
+    var hour: TimeInterval         { get }
+    var hours: TimeInterval        { get }
+    
+    var day: TimeInterval          { get }
+    var days: TimeInterval         { get }
+}
+public extension NumerToTime {
+    var millisecond: TimeInterval  { return num / 1000 }
+    var milliseconds: TimeInterval { return num / 1000 }
+    var ms: TimeInterval           { return num / 1000 }
+    
+    var second: TimeInterval       { return num }
+    var seconds: TimeInterval      { return num }
+    
+    var minute: TimeInterval       { return num * 60 }
+    var minutes: TimeInterval      { return num * 60 }
+    
+    var hour: TimeInterval         { return num * 3600 }
+    var hours: TimeInterval        { return num * 3600 }
+    
+    var day: TimeInterval          { return num * 3600 * 24 }
+    var days: TimeInterval         { return num * 3600 * 24 }
+}
+
+extension Int: NumerToTime {
+    public var num: TimeInterval { return TimeInterval(self) }
+}
+extension Double: NumerToTime {
+    public var num: TimeInterval { return self }
+}
+
+
diff --git a/LingQi/LingQi/Tools/ShareView.swift b/LingQi/LingQi/Tools/ShareView.swift
new file mode 100644 (file)
index 0000000..9bb1bc6
--- /dev/null
@@ -0,0 +1,140 @@
+////
+////  ShareView.swift
+////  Magpie
+////
+////  Created by incar on 2024/1/10.
+////
+//
+//import Foundation
+//extension UnAuthSchoolDetailVC{
+//    class AgreementView: YLPresentView {
+//        private let titleLabel = UILabel()
+//        private let des = UILabel()
+//        private let selectButton = UIButton()
+//        private let privacyLabel = UILabel()
+//        private let okButton = AnimationButton()
+//        private var vm:ClassDetailVM
+//        
+//        init(code:String) {
+//            self.vm = ClassDetailVM(code:code)
+//            super.init(contentHeight: 400.fitR)
+//        }
+//
+//        override func setupSubView() {
+//            super.setupSubView()
+//            contentView.addSubview(titleLabel)
+//            contentView.addSubview(des)
+//            contentView.addSubview(selectButton)
+//            contentView.addSubview(privacyLabel)
+//            contentView.addSubview(okButton)
+//        }
+//        override func setupLayout() {
+//            super.setupLayout()
+//            titleLabel.snp.makeConstraints { (m) in
+//                m.top.equalToSuperview().inset(25.fitR)
+//                m.left.right.equalToSuperview()
+//                m.height.greaterThanOrEqualTo(0)
+//            }
+//            des.snp.makeConstraints { (m) in
+//                m.left.right.equalToSuperview().inset(20.fitR)
+//                m.top.equalToSuperview().inset(67.fitR)
+//            }
+//            selectButton.snp.makeConstraints { (m) in
+//                m.left.equalToSuperview().inset(20.fitR)
+//                m.bottom.equalToSuperview().inset(96.fitR)
+//                m.height.equalTo(15.fitR)
+//                m.width.equalTo(15.fitR)
+//            }
+//            privacyLabel.snp.makeConstraints { (m) in
+//                m.left.equalTo(selectButton.snp.right)
+//                m.centerY.equalTo(selectButton)
+//            }
+//            okButton.snp.makeConstraints { (m) in
+//                m.bottom.equalToSuperview().inset(30.fitR)
+//                m.height.equalTo(44.fitR)
+//                m.left.right.equalToSuperview().inset(25.fitR)
+//            }
+//        }
+//        
+//        override func setupStyle() {
+//            super.setupStyle()
+//            titleLabel.do { (v) in
+//                v.textColor = .rgb(0x333333)
+//                v.font = .semiBold(16)
+//                v.textAlignment = .center
+//                v.text = "诸葛驾到代运营协议说明"
+//            }
+//            des.do { (v) in
+//                v.text = "1.用户通过诸葛驾到寻找到合适的驾校后,委托诸葛驾到负责撮合驾校学车的服务提供方,为用户代报名指定班型的学车服务,在代报名过程中提供驾校信息核验、学车权益守护、学车资金托管、代理结算等服务。具体服务内容由诸葛驾到根据实际情况提供,包括但不限于: (1) 作为用户的学车经纪人代表用户与驾校签约学车报名协议;(2)学车报名资金的托管; (3) 维护用户在驾校学车的约定权益;(4) 服务商收入结算和用户支付费用:具体金额以产生的统计数据为准;(5) 订单查询;2.用户通过诸葛驾到完成的学车报名信息以平台发布的相应信息为准,交易应签署《学车报名服务合同》。具体内容《学车报名服务合同》以约定为准,该合同文本格式由诸葛驾到平台的驾校提供,经诸葛驾到平台撮合,由用户与诸葛驾到平台的驾校直接签约。所有发给用户的通告及其他消息都可通过APP或者用户所提供的联系方式发送 。"
+//                v.textAlignment = .left
+//                v.numberOfLines = 0
+//                v.font = .regular(12)
+//                v.textColor = .rgb(0x666666)
+//            }
+//            selectButton.do { (v) in
+//                v.yc.setBorder(width: 1.fitR, color: .rgb(0x999999), radius: 2.fitR)
+//                v.setImage(nil, for: .normal)
+//                v.addTarget(self, action: #selector(selectBtnAction), for: .touchUpInside)
+//            }
+//            privacyLabel.do { (v) in
+//                v.text = "  已阅读同意协议说明"
+//                v.textAlignment = .left
+//                v.numberOfLines = 1
+//                v.font = .regular(12)
+//                v.textColor = .rgb(0x999999)
+//                privacyLabel.yc.addTap(target: self, action: #selector(selectBtnAction))
+//            }
+//            okButton.do { (v) in
+//                v.isEnabled = false
+//                v.yc.addGardiendLayerWith(colors: [.color(.mainBlue),.color(.mainBlue)], frame: CGRect(x: 0, y: 0, width: kScreenWid - 50.fitR, height: 44.fitR), direction: .left2right)
+//                v.setTitle("下一步", for: .normal)
+//                v.setTitleColor(.color(.white), for: .normal)
+//                v.titleLabel?.font = .regular(15)
+//                v.yc.setCornerRadius(22.fitR)
+//                v.alpha = 0.5
+//                v.addTarget(self, action: #selector(okButtonAction), for: .touchUpInside)
+//                self.selectBtnAction()
+//
+//            }
+//        }
+//        @objc func okButtonAction(){
+////            self.okButtonTap?()
+////            hide()
+//            self.start2LoadData()
+//        }
+//        @objc func selectBtnAction(){
+//            selectButton.isSelected = !selectButton.isSelected
+//            if selectButton.isSelected {
+//                selectButton.yc.setBorder(width: 1.fitR, color: .rgb(0x036AFF), radius: 2.fitR)
+//                selectButton.setImage(UIImage(named: "agreement_selected"), for: .normal)
+//                privacyLabel.textColor = .rgb(0x036AFF)
+//                okButton.alpha = 1
+//            }
+//            else{
+//                selectButton.yc.setBorder(width: 1.fitR, color: .rgb(0x999999), radius: 2.fitR)
+//                selectButton.setImage(nil, for: .normal)
+//                privacyLabel.textColor = .rgb(0x999999)
+//                okButton.alpha = 0.5
+//            }
+//            okButton.isEnabled = selectButton.isSelected
+//        }
+//        
+//        func start2LoadData(){
+//            SVProgressHUD.showLoading()
+//            SVProgressHUD.setContainerView(app.window)
+//            self.vm.fetchClassDetail{[weak self] (model) in
+//                guard let self = self else {return}
+//                if model.isSuccess{
+//                    SVProgressHUD.hidden()
+//                    self.hide()
+//                    let params = PayDetailVCParams(model:model.data)
+//                    let vc = PayDetailVC(data: params)
+//                    UIViewController.yc.currentNav?.pushViewController(vc, animated: true)
+//                }
+//                else{
+//                    SVProgressHUD.showAutoHiden(model.msg)
+//                }
+//            }
+//        }
+//    }
+//}
diff --git a/LingQi/LingQi/Tools/SizeFit.swift b/LingQi/LingQi/Tools/SizeFit.swift
new file mode 100644 (file)
index 0000000..875b57f
--- /dev/null
@@ -0,0 +1,90 @@
+//
+//  SizeFit.swift
+//  zgjd
+//
+//  Created by apple on 2020/11/9.
+//
+
+import UIKit
+
+final class ScreenSize {
+    
+    static let shared = ScreenSize()
+    init() {
+        p_refreshData()
+    }
+    
+    private(set) var screenWidthRatio: CGFloat = 1
+    private(set) var screenHeightRatio: CGFloat = 1
+    private(set) var isIphonex = false
+    
+    //  默认参考 size = (375,667)
+    private let designSize = CGSize.init(width: 375, height: 667)
+    private func p_refreshData() {
+        let screenWidth = UIScreen.main.bounds.size.width
+        let screenHeight = UIScreen.main.bounds.size.height
+        screenWidthRatio = screenWidth / designSize.width
+        screenHeightRatio = screenHeight / designSize.height
+                
+        if #available(iOS 11.0, *),
+           UIApplication.shared.delegate?
+                .window??.safeAreaInsets.bottom != 0 {
+            isIphonex = true
+        }
+    }
+}
+
+
+public protocol SizeTransform {
+    var cgFloat: CGFloat    { get }
+    var round: CGFloat      { get }
+    var ceil: CGFloat       { get }
+    var floor: CGFloat      { get }
+    var abs: CGFloat        { get }
+    var fitR: CGFloat       { get }
+    var fitC: CGFloat       { get }
+    var fitF: CGFloat       { get }
+    var fitT: CGFloat       { get }
+    
+    var double: Double      { get }
+    var float: Float        { get }
+    var half: CGFloat       { get }
+    var int: Int            { get }
+}
+
+public extension SizeTransform {
+    
+    var round: CGFloat { return CGFloat(roundf(float)) }
+    var ceil: CGFloat  { return CGFloat(ceilf(float)) }
+    var floor: CGFloat { return CGFloat(floorf(float)) }
+    var abs: CGFloat { return CGFloat(fabsf(float)) }
+    var fitR: CGFloat
+    { return  (ScreenSize.shared.screenWidthRatio * cgFloat).round }
+    var fitC: CGFloat
+    { return (ScreenSize.shared.screenWidthRatio * cgFloat).ceil }
+    var fitF: CGFloat
+    { return (ScreenSize.shared.screenWidthRatio * cgFloat).floor }
+    var fitT: CGFloat
+    { return (ScreenSize.shared.screenWidthRatio * cgFloat) }
+    
+    var double: Double { return Double(cgFloat) }
+    var float: Float   { return Float(cgFloat) }
+    var half: CGFloat  { return cgFloat * 0.5 }
+    var int: Int       { return Int(float) }
+}
+
+extension Int: SizeTransform {
+    public var cgFloat: CGFloat { return CGFloat(self) }
+    public var int: Int         { return self }
+}
+extension CGFloat: SizeTransform {
+    public var cgFloat: CGFloat { return self }
+}
+extension Double: SizeTransform {
+    public var cgFloat: CGFloat { return CGFloat(self) }
+    public var double: Double   { return self }
+}
+extension Float: SizeTransform {
+    public var cgFloat: CGFloat { return CGFloat(self) }
+    public var float: Float     { return self }
+}
diff --git a/LingQi/LingQi/Tools/Then.swift b/LingQi/LingQi/Tools/Then.swift
new file mode 100755 (executable)
index 0000000..c7e0966
--- /dev/null
@@ -0,0 +1,105 @@
+// The MIT License (MIT)
+//
+// Copyright (c) 2015 Suyeol Jeon (xoul.kr)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+import Foundation
+import CoreGraphics
+#if os(iOS) || os(tvOS)
+  import UIKit.UIGeometry
+#endif
+
+public protocol Then {}
+
+extension Then where Self: Any {
+
+  /// Makes it available to set properties with closures just after initializing and copying the value types.
+  ///
+  ///     let frame = CGRect().with {
+  ///       $0.origin.x = 10
+  ///       $0.size.width = 100
+  ///     }
+  public func with(_ block: (inout Self) throws -> Void) rethrows -> Self {
+    var copy = self
+    try block(&copy)
+    return copy
+  }
+
+  /// Makes it available to execute something with closures.
+  ///
+  ///     UserDefaults.standard.do {
+  ///       $0.set("devxoul", forKey: "username")
+  ///       $0.set("devxoul@gmail.com", forKey: "email")
+  ///       $0.synchronize()
+  ///     }
+  public func `do`(_ block: (Self) throws -> Void) rethrows {
+    try block(self)
+  }
+
+}
+
+extension Then where Self: AnyObject {
+
+  /// Makes it available to set properties with closures just after initializing.
+  ///
+  ///     let label = UILabel().then {
+  ///       $0.textAlignment = .center
+  ///       $0.textColor = UIColor.black
+  ///       $0.text = "Hello, World!"
+  ///     }
+  public func then(_ block: (Self) throws -> Void) rethrows -> Self {
+    try block(self)
+    return self
+  }
+
+}
+
+extension NSObject: Then {}
+
+extension CGPoint: Then {}
+extension CGRect: Then {}
+extension CGSize: Then {}
+extension CGVector: Then {}
+extension Array: Then {}
+extension Dictionary: Then {}
+extension Set: Then {}
+
+#if os(iOS) || os(tvOS)
+  extension UIEdgeInsets: Then {}
+  extension UIOffset: Then {}
+  extension UIRectEdge: Then {}
+#endif
+
+
+extension Then where Self: UIView {
+    public func add(toSuperView superView: UIView) -> Self {
+        guard superview != self else { return self }
+        superView.addSubview(self)
+        return self
+    }
+}
+
+extension Array where Element: UIView {
+    public func `do`(_ block: (Element) throws -> Void) rethrows {
+        for e in self {
+            try block(e)
+        }
+    }
+}
diff --git a/LingQi/LingQi/Tools/TimerButton/YLTimerButton.h b/LingQi/LingQi/Tools/TimerButton/YLTimerButton.h
new file mode 100644 (file)
index 0000000..1d10193
--- /dev/null
@@ -0,0 +1,15 @@
+//
+//  YLTimerButton.h
+//  YLProject
+//
+//  Created by Mac01 on 2018/3/24.
+//  Copyright © 2018年 Mac01. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+@interface YLTimerButton : UIButton
+@property(nonatomic, strong) UILabel *label;
+@property(nonatomic, assign) NSInteger maxCount;
+
+- (void)start;
+@end
diff --git a/LingQi/LingQi/Tools/TimerButton/YLTimerButton.m b/LingQi/LingQi/Tools/TimerButton/YLTimerButton.m
new file mode 100644 (file)
index 0000000..69e075a
--- /dev/null
@@ -0,0 +1,114 @@
+//
+//  YLTimerButton.m
+//  YLProject
+//
+//  Created by Mac01 on 2018/3/24.
+//  Copyright © 2018年 Mac01. All rights reserved.
+//
+
+#import "YLTimerButton.h"
+
+
+@interface YLTimerButton ()
+
+@property(nonatomic, assign) NSInteger second;
+@property(nonatomic, strong) NSTimer *timer;
+@property(nonatomic, strong) NSDate *lastTime;
+@end
+
+@implementation YLTimerButton
+
+- (instancetype)initWithFrame:(CGRect)frame{
+    if (self = [super initWithFrame:frame]) {
+        self.maxCount = 60;
+
+        [self setTitle:@"" forState:UIControlStateNormal];
+        self.titleLabel.font = [UIFont systemFontOfSize:14];
+        
+        self.layer.cornerRadius = 5;
+        self.layer.masksToBounds = YES;
+        
+        self.label = [[UILabel alloc]initWithFrame:self.bounds];
+        self.label.text = @"获取验证码";
+        self.label.font = [UIFont systemFontOfSize:14];
+        self.label.textColor = [UIColor blueColor];
+        self.label.textAlignment = NSTextAlignmentCenter;
+        self.label.backgroundColor = [UIColor clearColor];
+        [self addSubview:self.label];
+        
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(enterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(becomeActive) name:UIApplicationDidBecomeActiveNotification object:nil];
+    }
+    return self;
+}
+
+-(void)layoutSubviews{
+    [super layoutSubviews];
+    self.label.frame = self.bounds;
+//    self.backgroundColor = [UIColor redColor];
+}
+
+- (void)start {
+    self.enabled = NO;
+    self.second = self.maxCount;
+    self.label.textColor = [UIColor colorWithRed:67/255.0f green:155/255.0f blue:255/255.0f alpha:1.0f];
+    self.label.text = [NSString stringWithFormat:@"%ld秒",self.second];
+    self.timer = [NSTimer scheduledTimerWithTimeInterval:1
+                                                  target:self
+                                                selector:@selector(count)
+                                                userInfo:nil
+                                                 repeats:YES];
+}
+
+- (void)stop {
+    self.enabled = YES;
+    self.label.text = @"发送验证码";
+    self.label.textColor = [UIColor colorWithRed:67/255.0f green:155/255.0f blue:255/255.0f alpha:1.0f];
+    if ([self.timer isValid]) {
+        [self.timer invalidate];
+    }
+}
+
+- (void)count {
+    self.second--;
+    if (self.second < 0) {
+        self.second = 0;
+    }
+    
+    self.label.text = [NSString stringWithFormat:@"%ldS", (long)self.second];
+    if (self.second == 0) {
+        [self stop];
+    }
+}
+
+
+#pragma mark - notification
+- (void)enterBackground{
+    if ([self.timer isValid]) {
+        [self.timer invalidate];
+        self.lastTime = [NSDate date];
+    }
+    else{
+        self.lastTime = nil;
+    }
+}
+
+- (void)becomeActive{
+    if (self.lastTime == nil) {
+        return;
+    }
+    NSInteger count = [self.lastTime timeIntervalSinceNow];
+    self.second -= ABS(count);
+    if (self.second > 0) {
+        self.timer = [NSTimer scheduledTimerWithTimeInterval:1
+                                                      target:self
+                                                    selector:@selector(count)
+                                                    userInfo:nil
+                                                     repeats:YES];
+    }
+    else{
+        [self count];
+    }
+}
+@end
+
diff --git a/LingQi/LingQi/UI/Base/BaseNC.swift b/LingQi/LingQi/UI/Base/BaseNC.swift
new file mode 100644 (file)
index 0000000..22ca3c8
--- /dev/null
@@ -0,0 +1,16 @@
+//
+//  BaseNC.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/2.
+//
+
+import UIKit
+
+class BaseNC:UINavigationController{
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        
+    }
+}
diff --git a/LingQi/LingQi/UI/Base/BaseNavigation.swift b/LingQi/LingQi/UI/Base/BaseNavigation.swift
new file mode 100644 (file)
index 0000000..1827b08
--- /dev/null
@@ -0,0 +1,173 @@
+//
+//  YLNavBar.swift
+//  zgjd
+//
+//  Created by apple on 2020/11/10.
+//
+
+import UIKit
+
+public enum BaseNavigationLeftStyle {
+    case back
+    case close
+    case title(NSAttributedString)
+    case image(UIImage?)
+}
+
+public enum BaseNavigationRightStyle {
+    case share
+    case title(String, norColor: UIColor, disColor: UIColor)
+    case image(UIImage?)
+}
+
+public enum BaseNavigationTitleStyle {
+    case `default`
+    case custom(titleColor: UIColor, bgColor: UIColor)
+    case attrTitle(NSAttributedString)
+}
+
+public protocol BaseNavigationBarDelegate: NSObjectProtocol {
+    func navleftViewTapped()
+    func navRightViewTapped()
+}
+
+public class BaseNavigationBar: UIView {
+    
+    public weak var delegate: BaseNavigationBarDelegate?
+    public let alphaBgView = UIView()
+    public let leftView = UIButton()
+    public let titleLabel = UILabel()
+    public let separatorLine = UIView()
+    public lazy var rightView:    UIButton = {
+        return setupRightView()
+    }()
+    
+    private var navTitle: String
+    public init(title: String = "", delegate: BaseNavigationBarDelegate? = nil) {
+        self.navTitle = title
+        self.delegate = delegate
+        super.init(frame: .zero)
+        
+        setupLayout()
+        setupStyle()
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    var title: String {
+        get { return titleLabel.text ?? "" }
+        set { titleLabel.text = newValue }
+    }
+    
+    func setupLeftStyle(_ style: BaseNavigationLeftStyle) {
+        switch style {
+        case .back:
+            leftView.setImage(UIImage(named: "arrow_left_1"), for: .normal)
+        case .close:
+            leftView.setImage(UIImage(named: "arrow_left_1"), for: .normal)
+        case .title(let attrStr):
+            leftView.setImage(nil, for: .normal)
+            leftView.setAttributedTitle(attrStr, for: .normal)
+        case .image(let image):
+            leftView.setImage(image, for: .normal)
+        }
+    }
+    
+    func setRightStyle(_ style: BaseNavigationRightStyle) -> UIButton {
+        switch style {
+        case .share:
+            let img = UIImage.init(named: "card_detail_share_black")?.withRenderingMode(.alwaysOriginal)
+            rightView.setImage(img, for: .normal)
+        case .image(let image):
+            rightView.setImage(image, for: .normal)
+        case .title(let title, let norColor, let disColor):
+            rightView.setTitle(title, for: .normal)
+            rightView.setTitleColor(norColor, for: .normal)
+            rightView.setTitleColor(disColor, for: .disabled)
+        }
+        return rightView
+    }
+    
+    func setTitleStyle(_ style: BaseNavigationTitleStyle) {
+        switch style {
+        case .default:
+            titleLabel.textColor = .white
+            self.backgroundColor = .white
+        case .custom(let titleColor,let bgColor):
+            titleLabel.textColor = titleColor
+            self.backgroundColor = bgColor
+        case .attrTitle(let attrStr):
+            titleLabel.attributedText = attrStr
+            
+        }
+    }
+    @objc func leftViewTapped() {
+        delegate?.navleftViewTapped()
+    }
+    @objc func rightViewTapped() {
+        delegate?.navRightViewTapped()
+    }
+    func setupLayout() {
+        addSubview(alphaBgView)
+        addSubview(titleLabel)
+        addSubview(leftView)
+        addSubview(separatorLine)
+        let h = kNavBtm
+        self.frame = CGRect(x: 0, y: 0, width: kScreenWid, height: h)
+        alphaBgView.frame = CGRect(x: 0, y: 0, width: kScreenWid, height: h)
+        separatorLine.frame = CGRect(x: 0, y: h - 1, width: kScreenWid, height: 1)
+        
+        titleLabel.snp.makeConstraints { (m) in
+            m.leading.trailing.equalToSuperview().inset(60)
+            m.top.equalTo(kNavTop)
+            m.height.equalTo(44)
+        }
+        leftView.snp.makeConstraints { (m) in
+            m.leading.equalToSuperview()
+            m.top.equalTo(kNavTop)
+            m.bottom.equalToSuperview()
+            m.width.greaterThanOrEqualTo(48)
+        }
+    }
+    
+    func setupStyle() {
+        backgroundColor = .rgb(0x11131E)
+        alphaBgView.backgroundColor = UIColor.white
+        alphaBgView.alpha = 0
+        separatorLine.backgroundColor = .color(.separateLine)
+        separatorLine.isHidden = true
+        
+        titleLabel.do { (v) in
+            v.textColor = .white
+            v.font = .medium(16)
+            v.textAlignment = .center
+            v.lineBreakMode = .byTruncatingTail
+            v.text = navTitle
+        }
+        leftView.do { (v) in
+            v.contentEdgeInsets = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 0)
+            v.contentHorizontalAlignment = .left
+            v.setImage(UIImage(named: "arrow_back"), for: .normal)
+            v.addTarget(self, action: #selector(leftViewTapped), for: .touchUpInside)
+        }
+    }
+    
+    func setupRightView() -> UIButton {
+        let rightBtn = UIButton()
+        addSubview(rightBtn)
+        rightBtn.snp.makeConstraints { (m) in
+            m.top.equalTo(kNavTop)
+            m.trailing.bottom.equalToSuperview()
+            m.width.greaterThanOrEqualTo(48)
+        }
+        rightBtn.do { (v) in
+            v.setTitleColor(.rgb(0x222222), for: .normal)
+            v.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 15)
+            v.imageView?.contentMode = .right
+            v.addTarget(self, action: #selector(rightViewTapped), for: .touchUpInside)
+        }
+        return rightBtn
+    }
+}
diff --git a/LingQi/LingQi/UI/Base/BasePickerView.swift b/LingQi/LingQi/UI/Base/BasePickerView.swift
new file mode 100644 (file)
index 0000000..db385a6
--- /dev/null
@@ -0,0 +1,86 @@
+//
+//  YLDatePicker.swift
+//  YLDatePicker
+//
+//  Created by yl on 2017/11/15.
+//  Copyright © 2017年 February12. All rights reserved.
+//
+
+import Foundation
+import UIKit
+
+
+class BasePickerView: BasePresentView {
+
+    var didSelectRowBlock: ((_ row:Int)->Void)?
+
+    var dataArray = ["1","2","3","4","5","6","7","8"]
+
+//    private(set) var _currentDate = Date()
+
+    var datePicker =  UIPickerView(frame: CGRect(x: 0, y:0, width: kScreenWid, height: 300.fitR))
+
+    private let titleLabel = UILabel()
+    private let des = UILabel()
+    private let selectButton = UIButton()
+    private let privacyLabel = UILabel()
+    private let okButton = UIButton()
+    
+    init() {
+        super.init(contentHeight: 300.fitR)
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    override func setupSubView() {
+        super.setupSubView()
+
+    }
+    override func setupLayout() {
+        super.setupLayout()
+        contentView.addSubview(datePicker)
+    }
+    
+    override func setupStyle() {
+        super.setupStyle()
+        // 时间控件
+        datePicker.delegate = self
+        datePicker.dataSource = self
+        datePicker.backgroundColor = UIColor.clear
+        
+//        scrollToDate(components: dateComponentOrder, animated: false)
+//        datePicker.addLayoutConstraints(attributes: [.left,.right,.top], toItem: self, attributes: nil, constants: [0,0,0])
+    }
+    func setupData(_ list:[String]){
+        dataArray = list
+        datePicker.reloadAllComponents()
+    }
+    func selectedIndex(_ index:Int){
+        datePicker.selectRow(index, inComponent: 0, animated: false)
+    }
+}
+
+extension BasePickerView: UIPickerViewDelegate, UIPickerViewDataSource {
+    public func numberOfComponents(in pickerView: UIPickerView) -> Int {
+        return 1
+    }
+
+    public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
+        return dataArray.count
+    }
+
+    public func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
+        return dataArray[row]
+    }
+
+    public func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
+        return 43.fitR
+    }
+
+    public func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
+        didSelectRowBlock?(row)
+    }
+}
+
diff --git a/LingQi/LingQi/UI/Base/BasePresentView.swift b/LingQi/LingQi/UI/Base/BasePresentView.swift
new file mode 100644 (file)
index 0000000..a0a2c0e
--- /dev/null
@@ -0,0 +1,78 @@
+//
+//  SchoolntroView.swift
+//  zgjd
+//
+//  Created by apple on 2021/1/22.
+//
+
+
+import UIKit
+class BasePresentView: UIView {
+    let bgView = UIView()
+    let contentView = UIView()
+    var contentH: CGFloat = 250.fitR
+    init(contentHeight:CGFloat,backgroundEnabled:Bool = true) {
+        self.contentH = contentHeight
+        super.init(frame: CGRect(x: 0, y: 0, width: kScreenWid, height: kScreenHei))
+        setupSubView()
+        setupLayout()
+        setupStyle()
+        if backgroundEnabled {
+            bgView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(hide)))
+        }
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    func setupSubView(){
+        addSubview(bgView)
+        addSubview(contentView)
+    }
+
+    func setupLayout(){
+        bgView.snp.makeConstraints { (make) in
+            make.edges.equalToSuperview()
+        }
+        contentView.snp.makeConstraints { (make) in
+            make.leading.trailing.bottom.equalToSuperview()
+            make.height.equalTo(contentH)
+        }
+    }
+    func setupStyle(){
+        backgroundColor = UIColor.clear
+        bgView.backgroundColor = UIColor.init(white: 0, alpha: 0.5)
+        
+        contentView.do { (v) in
+            v.backgroundColor = .white
+            v.yc.setCorners(withRoundedRect: CGRect(x: 0, y: 0, width: kScreenWid, height: self.contentH), roundingCorners: [.topLeft,.topRight], cornerRadii: CGSize(width: 10.fitR, height: 10.fitR))
+        }
+    }
+    func show(animate:Bool = true) -> Void {
+//        app.window?.addSubview(self)
+        
+        if(animate){
+            self.contentView.transform = CGAffineTransform.init(translationX: 0, y: self.contentH)
+            UIView.animate(withDuration: 0.2) {
+                self.contentView.transform = CGAffineTransform.identity
+                self.layer.opacity = 1.0
+            }
+        }
+        else{
+            self.contentView.transform = CGAffineTransform.init(translationX: 0, y: self.contentH)
+            self.contentView.transform = CGAffineTransform.identity
+            UIView.animate(withDuration: 0.2) {
+                self.layer.opacity = 1.0
+            }
+        }
+    }
+    
+    @objc func hide() -> Void {
+        UIView.animate(withDuration: 0.2, animations: {
+            self.contentView.transform = CGAffineTransform.init(translationX: 0, y: self.contentH)
+            self.layer.opacity = 0.0
+        }) { (finished) in
+            self.removeFromSuperview()
+        }
+    }
+}
diff --git a/LingQi/LingQi/UI/Base/BaseTC.swift b/LingQi/LingQi/UI/Base/BaseTC.swift
new file mode 100644 (file)
index 0000000..2fbc825
--- /dev/null
@@ -0,0 +1,42 @@
+//
+//  BaseTC.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/2.
+//
+
+import UIKit
+
+class BaseTC:UITabBarController{
+    let homeVC = HomeVC()
+    let mine = MineVC()
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+
+        // Do any additional setup after loading the view.
+        view.backgroundColor = .color(.bgColor)
+        setupUI()
+    }
+    
+
+    func setupUI(){
+        self.tabBar.backgroundColor = .rgb(0x212935)
+        let item0 = UITabBarItem(title: "home", image: UIImage(named: "tab_0_normal")?.withRenderingMode(.alwaysOriginal), selectedImage: UIImage(named: "tab_0_selected")?.withRenderingMode(.alwaysOriginal))
+        let nc0 = BaseNC(rootViewController: homeVC)
+        nc0.tabBarItem = item0
+        
+        let item1 = UITabBarItem(title: "set", image: UIImage(named: "tab_1_normal")?.withRenderingMode(.alwaysOriginal), selectedImage: UIImage(named: "tab_1_selected")?.withRenderingMode(.alwaysOriginal))
+        let nc1 = BaseNC(rootViewController: mine)
+        nc1.tabBarItem = item1
+        self.viewControllers = [nc0,nc1]
+        
+        let appearance = UITabBarAppearance()
+        appearance.configureWithDefaultBackground()
+        appearance.stackedLayoutAppearance.normal.titleTextAttributes = [NSAttributedString.Key.foregroundColor:UIColor.white.withAlphaComponent(0.5)]
+        appearance.stackedLayoutAppearance.selected.titleTextAttributes = [NSAttributedString.Key.foregroundColor:UIColor.color(.theme)]
+        self.tabBar.standardAppearance = appearance
+        
+        self.selectedIndex = 1
+    }
+}
diff --git a/LingQi/LingQi/UI/Base/BaseTableViewCell.swift b/LingQi/LingQi/UI/Base/BaseTableViewCell.swift
new file mode 100644 (file)
index 0000000..a0ebf68
--- /dev/null
@@ -0,0 +1,56 @@
+//
+//  BaseTableViewCell.swift
+//  zgjd
+//
+//  Created by Kylin on 11/24/20.
+//
+
+import UIKit
+extension BaseTableViewCell: YCTableViewCellInitProtocol { }
+class BaseTableViewCell: UITableViewCell {
+
+    // 记录当前位置
+    var indexPath : NSIndexPath? = nil
+   
+    override func awakeFromNib() {
+        super.awakeFromNib() 
+        // Initialization code
+        selectionStyle = .none
+        contentView.backgroundColor = .clear
+    }
+
+    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+        super.init(style:style, reuseIdentifier: reuseIdentifier)
+        selectionStyle = .none
+        contentView.backgroundColor = .clear
+        
+        setupViews()
+        setupLayout()
+    }
+    
+    required init?(coder: NSCoder) {
+        super.init(coder: coder)
+//        fatalError("init(coder:) has not been implemented")
+    }
+    override func setSelected(_ selected: Bool, animated: Bool) {
+        super.setSelected(selected, animated: animated)
+
+        // Configure the view for the selected state
+    }
+
+    // 通过类名获取
+    static func reuseID()-> String{
+       return String(describing: Self.classForCoder())
+    }
+    
+    // 从xib 中获取
+    static func cellForNib()-> UINib{
+        return UINib.init(nibName: String(describing: Self.classForCoder()), bundle: nil)
+    }
+    func setupViews(){
+        
+    }
+    func setupLayout(){
+        
+    }
+}
diff --git a/LingQi/LingQi/UI/Base/BaseTableViewSetionHeader.swift b/LingQi/LingQi/UI/Base/BaseTableViewSetionHeader.swift
new file mode 100644 (file)
index 0000000..b21724e
--- /dev/null
@@ -0,0 +1,29 @@
+//
+//  BaseTableViewSetionHeader.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/31.
+//
+
+
+import UIKit
+
+extension BaseTableViewSetionHeader: YCTableHeaderFooterInitProtocol { }
+class BaseTableViewSetionHeader: UITableViewHeaderFooterView {
+    override init(reuseIdentifier: String?) {
+        super.init(reuseIdentifier: reuseIdentifier)
+        
+        setupViews()
+        setupLayout()
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    func setupViews(){
+        
+    }
+    func setupLayout(){
+        
+    }
+}
diff --git a/LingQi/LingQi/UI/Base/BaseTextField.swift b/LingQi/LingQi/UI/Base/BaseTextField.swift
new file mode 100644 (file)
index 0000000..4565bc2
--- /dev/null
@@ -0,0 +1,73 @@
+//
+//  YLTextField.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/10.
+//
+
+import UIKit
+
+open class BaseTextField: UITextField {
+    
+    public var maxLenth: Int
+    public init(maxLenth: Int = 1000) {
+        self.maxLenth = maxLenth
+        super.init(frame: .zero)
+        
+        borderStyle = .none
+        textAlignment = .left
+        autocorrectionType = .no
+        autocapitalizationType = .none
+        enablesReturnKeyAutomatically = true
+        tintColor = .color(.theme)
+        addTarget(self, action: #selector(p_textFieldDidChange(_:)), for: .editingChanged)
+    }
+    
+    
+    // MARK: === 输入长度限制
+    @objc func p_textFieldDidChange(_ textFiled: UITextField) {
+        guard maxLenth > 0 else { return }
+        if textFiled.text!.count > maxLenth {
+            textFiled.text = NSString(string: textFiled.text!).substring(to: maxLenth)
+        }
+    }
+    
+    required public init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    /*   小数点后两位 判断
+    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
+        // 只允许输入 0-9和.
+        if !string.el.isValidMoneyNum,
+            string != "" { return false }
+        // 如果输入的是“.”  判断之前已经有"."或者字符串为空
+        if string == "." {
+            if textField.text?.range(of: ".") != nil ||
+                textField.text == "" {
+                return false
+            }
+        }
+        if string != "" {
+            // 防止出现 0543
+            if textField.text == "0",
+                string != "." { return false }
+                // 防止出现 0.00
+            else if textField.text == "0.0",
+                string == "0" {
+                return false
+            }
+        }
+        guard let _ = textField.text?.range(of: ".") else {
+            return true }
+        let nsStr = NSString.init(string: textField.text!)
+        let location = nsStr.range(of: ".").location
+        if nsStr.length > location + 2,
+            string != "" {
+            return false
+        }
+        return true
+    }
+     */
+}
+
diff --git a/LingQi/LingQi/UI/Base/BaseVC.swift b/LingQi/LingQi/UI/Base/BaseVC.swift
new file mode 100644 (file)
index 0000000..cae232c
--- /dev/null
@@ -0,0 +1,120 @@
+//
+//  BaseVC.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/2.
+//
+
+import UIKit
+import Kingfisher
+
+open class BaseVC:UIViewController, UIGestureRecognizerDelegate {
+    
+    
+    let navBar = BaseNavigationBar()
+
+    public init() {
+        super.init(nibName: nil, bundle: nil)
+    }
+    
+    @available(*, unavailable, message: "Loading this view controller from a nib is unsupported")
+    public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
+        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
+    }
+    
+    @available(*, unavailable, message: "Loading this view controller from a nib is unsupported")
+    public required init(coder aDecoder: NSCoder) {
+        fatalError("Loading this view controller from a nib is unsupported")
+    }
+    
+    override open func viewDidLoad() {
+        super.viewDidLoad()
+        navBar.delegate = self
+        view.backgroundColor = .rgb(0x11131E)
+        view.addSubview(navBar)
+//        self.automaticallyAdjustsScrollViewInsets = false
+        navigationController?.navigationBar.isHidden = true
+        hidesBottomBarWhenPushed = true
+        
+        setupViews()
+        setupLayout()
+    }
+    open override func viewDidAppear(_ animated: Bool) {
+        super.viewDidAppear(animated)
+        self.navigationController?.navigationBar.isHidden = true
+    }
+
+    
+    deinit {
+        k_logViewControllerDeinit(self)
+    }
+    
+    override open func didReceiveMemoryWarning() {
+        super.didReceiveMemoryWarning()
+        KingfisherManager.shared.cache.clearMemoryCache()
+    }
+    
+    override open var preferredStatusBarStyle: UIStatusBarStyle {
+        if #available(iOS 13.0, *) {
+            return .darkContent
+        } else {
+            return .default
+        }
+    }
+
+    func setupViews(){
+        
+    }
+    func setupLayout(){
+        
+    }
+}
+
+extension BaseVC: BaseNavigationBarDelegate {
+    @objc public func navleftViewTapped() {
+        if let _ = self.presentingViewController {
+            self.dismiss(animated: true, completion: nil)
+        } else if let nav = self.navigationController {
+            nav.popViewController(animated: true)
+        }
+    }
+    
+    @objc public func navRightViewTapped() {
+        
+    }
+    
+    @discardableResult
+    public func setNavLeft(icon: UIImage?) -> UIButton {
+        navBar.leftView.setImage(icon, for: .normal)
+        return navBar.leftView
+    }
+    
+    @discardableResult
+    public func setNavLeft(title: String,
+                           titleColor: UIColor = .black,
+                           titleFont: UIFont = .regular(14, isFit: false)) -> UIButton {
+        navBar.leftView.setImage(nil, for: .normal)
+        navBar.leftView.setTitleColor(titleColor, for: .normal)
+        navBar.leftView.titleLabel?.font = titleFont
+        navBar.leftView.setTitle(title, for: .normal)
+        return navBar.leftView
+    }
+    
+    @discardableResult
+    public func setNavRight(icon: UIImage?) -> UIButton {
+        navBar.rightView.setImage(icon, for: .normal)
+        return navBar.rightView
+    }
+    
+    @discardableResult
+    public func setNavRight(title: String,
+                          norColor: UIColor = .black,
+                          disColor: UIColor = .gray,
+                          titleFont: UIFont = .regular(14, isFit: false)) -> UIButton {
+        navBar.rightView.setTitleColor(norColor, for: .normal)
+        navBar.rightView.setTitleColor(disColor, for: .disabled)
+        navBar.rightView.titleLabel?.font = titleFont
+        navBar.rightView.setTitle(title, for: .normal)
+        return navBar.rightView
+    }
+}
diff --git a/LingQi/LingQi/UI/Base/BaseVM.swift b/LingQi/LingQi/UI/Base/BaseVM.swift
new file mode 100644 (file)
index 0000000..18b49d2
--- /dev/null
@@ -0,0 +1,14 @@
+//
+//  BaseVM.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+class BaseVM {
+        
+    deinit {
+        k_logViewModelDeinit(self)
+    }
+    
+}
diff --git a/LingQi/LingQi/UI/Base/BaseView.swift b/LingQi/LingQi/UI/Base/BaseView.swift
new file mode 100644 (file)
index 0000000..925c378
--- /dev/null
@@ -0,0 +1,28 @@
+//
+//  BaseView.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+import UIKit
+
+class BaseView: UIView {
+    
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        setupViews()
+        setupLayout()
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    func setupViews(){
+        
+    }
+    func setupLayout(){
+        
+    }
+}
diff --git a/LingQi/LingQi/UI/Base/ReusabelViewsInitProtocol.swift b/LingQi/LingQi/UI/Base/ReusabelViewsInitProtocol.swift
new file mode 100644 (file)
index 0000000..9c458c5
--- /dev/null
@@ -0,0 +1,97 @@
+//
+//  ReusabelViewsInitProtocol.swift
+//  zgjd
+//
+//  Created by apple on 2020/11/10.
+//
+
+
+import UIKit
+
+///  UICollectionCell 快速初始化协议
+public protocol YCCollectionCellInitProtocol where Self: UICollectionViewCell {
+    static var reuseID: String { get }
+    static func cell(withCollectionView collectionView: UICollectionView, indexPath: IndexPath) -> Self
+}
+extension YCCollectionCellInitProtocol {
+    public static var reuseID: String {
+        return NSStringFromClass(Self.self).components(separatedBy: ".").last!
+    }
+    
+    public static func cell(withCollectionView collectionView: UICollectionView, indexPath: IndexPath) -> Self {
+        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseID, for: indexPath) as? Self else {
+            return Self(frame: .zero)
+        };  return cell
+    }
+}
+
+///  UITableViewCell 快速初始化协议
+public protocol YCTableViewCellInitProtocol where Self: UITableViewCell {
+    static var reuseID: String { get }
+    static func cell(withTableView tableView: UITableView, indexPath: IndexPath) -> Self
+}
+
+extension YCTableViewCellInitProtocol {
+    public static var reuseID: String {
+        return NSStringFromClass(Self.self).components(separatedBy: ".").last!
+    }
+    
+    public static func cell(withTableView tableView: UITableView, indexPath: IndexPath) -> Self {
+        guard let cell = tableView.dequeueReusableCell(withIdentifier: reuseID, for: indexPath) as? Self else {
+            return Self(style: .default, reuseIdentifier: reuseID)
+        };  return cell
+    }
+}
+
+///  UITableViewHeaderFooterView 快速初始化协议
+public protocol YCTableHeaderFooterInitProtocol where Self: UITableViewHeaderFooterView {
+    static var reuseID: String { get }
+    static func header(withTableView tableView: UITableView) -> Self
+    static func footer(withTableView tableView: UITableView) -> Self
+}
+
+extension YCTableHeaderFooterInitProtocol {
+    public static var reuseID: String {
+        return NSStringFromClass(Self.self).components(separatedBy: ".").last!
+    }
+    
+    public static func header(withTableView tableView: UITableView) -> Self {
+        guard let v = tableView.dequeueReusableHeaderFooterView(withIdentifier: reuseID) as? Self else {
+            return Self(reuseIdentifier: reuseID)
+        };  return v
+    }
+    
+    public static func footer(withTableView tableView: UITableView) -> Self {
+        guard let v = tableView.dequeueReusableHeaderFooterView(withIdentifier: reuseID) as? Self else {
+            return Self(reuseIdentifier: reuseID)
+        };  return v
+    }
+}
+
+
+///  YCColletionHeaderFooterInitProtocol 快速初始化协议
+public protocol YCColletionHeaderFooterInitProtocol where Self: UICollectionReusableView {
+    static var reuseID: String { get }
+    static func header(with collectionView: UICollectionView,indexPath: IndexPath) -> Self
+    static func footer(with collectionView: UICollectionView,indexPath: IndexPath) -> Self
+}
+
+extension YCColletionHeaderFooterInitProtocol {
+    public static var reuseID: String {
+        return NSStringFromClass(Self.self).components(separatedBy: ".").last!
+    }
+    
+    public static func header(with collectionView: UICollectionView,indexPath: IndexPath) -> Self {
+        guard let v  = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: reuseID, for: indexPath) as? Self else{
+            return Self()
+        }
+        return v
+    }
+    
+    public static func footer(with collectionView: UICollectionView,indexPath: IndexPath) -> Self {
+        guard let v  = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: reuseID, for: indexPath) as? Self else{
+            return Self()
+        }
+        return v
+    }
+}
diff --git a/LingQi/LingQi/UI/Base/WebView/BaseWebView.swift b/LingQi/LingQi/UI/Base/WebView/BaseWebView.swift
new file mode 100644 (file)
index 0000000..1df41eb
--- /dev/null
@@ -0,0 +1,32 @@
+//
+//  BaseWebView.swift
+//  zgjd
+//
+//  Created by apple on 2020/11/14.
+//
+
+import UIKit
+import WebKit
+
+open class BaseWebView: WKWebView {
+    
+    override public init(frame: CGRect, configuration: WKWebViewConfiguration) {
+        super.init(frame: frame, configuration: configuration)
+//        self.evaluateJavaScript("navigator.userAgent") { [weak self](result, error) in
+//            guard error == nil,
+//                var userAgent = result as? String else { return }
+//            if !userAgent.contains("/yc-ios") {
+//                userAgent.append("/yc-ios")
+//            }
+//            let dict = ["UserAgent": userAgent]
+//            UserDefaults.standard.register(defaults: dict)
+//            UserDefaults.standard.synchronize()
+//            self?.customUserAgent = userAgent
+//        }
+    }
+    
+    @available(*, unavailable, message: "Loading this view from a nib is unsupported")
+    public required init?(coder aDecoder: NSCoder) {
+        fatalError("Loading this view from a nib is unsupported")
+    }
+}
diff --git a/LingQi/LingQi/UI/Base/WebView/BaseWebViewController.swift b/LingQi/LingQi/UI/Base/WebView/BaseWebViewController.swift
new file mode 100644 (file)
index 0000000..1670a5b
--- /dev/null
@@ -0,0 +1,220 @@
+////
+////  BaseWebViewController.swift
+////  zgjd
+////
+////  Created by apple on 2020/11/14.
+////
+//
+//import UIKit
+//import WebKit
+//
+//struct BaseWebViewParams {
+//    var urlStr: String
+//    var request: URLRequest?
+//    var title: String
+//    init(urlStr: String, title: String = "") {
+//        self.urlStr = urlStr
+//        self.title = title
+//        self.request = nil
+//    }
+//    init(request: URLRequest, title: String = "") {
+//        self.request = request
+//        self.urlStr = ""
+//        self.title = title
+//    }
+//}
+//
+//final class BaseWebViewController: BaseVC {
+//    let webView = BaseWebView()
+//    private let progressView = UIProgressView(progressViewStyle: .default)
+//    private var initData: BaseWebViewParams
+//    init(initData: BaseWebViewParams) {
+//        
+//        self.initData = initData
+//        super.init()
+//    }
+//    
+//    
+//    deinit {
+//        webView.removeObserver(self, forKeyPath: "canGoBack")
+//        webView.removeObserver(self, forKeyPath: "estimatedProgress")
+//        webView.removeObserver(self, forKeyPath: "title")
+//    }
+//    override func viewDidLoad() {
+//        super.viewDidLoad()
+//        setupLayout()
+//        setupStyle()
+//    }
+//
+//    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
+//        if keyPath == "canGoBack" {
+//            if webView.canGoBack {
+//                self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true
+//            } else {
+//                self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
+//            }
+//        } else if keyPath == "estimatedProgress" {
+//            progressView.alpha = CGFloat(1.0 - webView.estimatedProgress) + 0.2
+//            let progerss = max(Float(webView.estimatedProgress), 0.1)
+//            progressView.setProgress(progerss, animated: true)
+//            if webView.estimatedProgress >= 1.0 {
+//                kDelay(0.3) {
+//                    self.progressView.alpha = 0.0
+//                    self.progressView.setProgress(0.0, animated: false)
+//                }
+//            }
+//        }else if keyPath == "title" {
+//            if initData.title.isEmpty {
+//                navBar.title = webView.title ?? " "
+//            }
+//            
+//        } else {
+//            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
+//        }
+//    }
+//}
+//
+//// MARK: - ********* webview delegate
+//extension BaseWebViewController: WKNavigationDelegate {
+//    
+//    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
+//        webView.evaluateJavaScript(
+//            "document.getElementsByTagName('body')[0].style.background='#FAFAFA'",
+//            completionHandler: nil)
+//    }
+//    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
+//        k_log("==== error: \(error)")
+//    }
+//    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
+//        k_log("==== error: \(error)")
+//    }
+//    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
+//        if (navigationAction.targetFrame == nil) {
+//            webView.load(navigationAction.request)
+//        }
+//        guard let policy = WKNavigationActionPolicy(rawValue: WKNavigationActionPolicy.allow.rawValue + 2)
+//            else { decisionHandler(.allow); return }
+//        decisionHandler(policy)
+//    }
+//}
+//
+//// MARK: - ********* UIResponse Funcs
+//extension BaseWebViewController {
+//    override func navleftViewTapped() {
+//        if webView.canGoBack {
+//            webView.goBack()
+//        }
+//        else{
+//            if let _ = self.presentingViewController {
+//                self.dismiss(animated: true, completion: nil)
+//            } else if let nav = self.navigationController {
+//                nav.popViewController(animated: true)
+//            }
+//        }
+//
+//    }
+//    override func navRightViewTapped() {
+//        if let _ = self.presentingViewController {
+//            self.dismiss(animated: true, completion: nil)
+//        } else if let nav = self.navigationController {
+//            nav.popViewController(animated: true)
+//        }
+//    }
+//}
+//
+//// MARK: - UI Setup
+//private extension BaseWebViewController {
+//    
+//    func setupLayout() {
+//        view.addSubview(webView)
+//        webView.addSubview(progressView)
+//    
+//        webView.snp.makeConstraints { (m) in
+//            m.top.equalToSuperview().inset(kNavBtm)
+//            m.bottom.equalToSuperview()
+//            m.leading.trailing.equalToSuperview()
+//        }
+//        progressView.snp.makeConstraints { (m) in
+//            m.top.leading.trailing.equalToSuperview()
+//            m.height.equalTo(2)
+//        }
+//    }
+//    
+//    func setupStyle() {
+//        
+//        navBar.title = initData.title
+//        setNavRight(title: "关闭",norColor: .color(.secondary))
+//        
+//        view.backgroundColor = .color(.viewBg)
+//        
+//        webView.navigationDelegate = self
+//        webView.uiDelegate = self
+//        webView.backgroundColor = .color(.viewBg)
+//
+//        webView.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil)
+//        webView.addObserver(self, forKeyPath: "canGoBack", options: .new, context: nil)
+//        webView.addObserver(self, forKeyPath: "title", options: .new, context: nil)
+//        webView.evaluateJavaScript("document.getElementsByTagName('body')[0].style.background='#FAFAFA'", completionHandler: nil)
+//        
+//        /// 加载URL
+//        if let requestUrl = initData.urlStr.yc.asUrl {
+//            let request = URLRequest(url: requestUrl)
+//            webView.load(request)
+//        }
+//        else if let request = initData.request {
+//            webView.load(request)
+//        }
+//        else { return }
+//        
+//        /// 进度条
+//        progressView.trackTintColor = .clear
+//        progressView.progressTintColor = .color(.theme)
+//        progressView.isHidden = false
+//        progressView.setProgress(0.05, animated: true)
+//        
+//    }
+//}
+//
+//// MARK: - WKUIDelegate 不实现该代理方法 网页内调用弹窗时会抛出异常,导致程序崩溃
+//extension BaseWebViewController: WKUIDelegate {
+//    // 获取js 里面的提示
+//    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
+//        if self.navigationController?.visibleViewController != self {
+//            completionHandler()
+//            return
+//        }
+//        let alert = UIAlertController(title: "提示", message: message, preferredStyle: .alert)
+//        alert.addAction(UIAlertAction(title: "确定", style: .default, handler: { (_) -> Void in
+//            completionHandler()
+//        }))
+//        alert.addAction(UIAlertAction(title: "取消", style: .cancel, handler: { (_) -> Void in
+//            completionHandler()
+//        }))
+//        self.present(alert, animated: true, completion: nil)
+//    }
+//    
+//    // js 信息的交流
+//    func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
+//        let alert = UIAlertController(title: "提示", message: message, preferredStyle: .alert)
+//        alert.addAction(UIAlertAction(title: "确定", style: .default, handler: { (_) -> Void in
+//            completionHandler(true)
+//        }))
+//        alert.addAction(UIAlertAction(title: "取消", style: .cancel, handler: { (_) -> Void in
+//            completionHandler(false)
+//        }))
+//        self.present(alert, animated: true, completion: nil)
+//    }
+//    
+//    // 交互。可输入的文本。
+//    func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
+//        let alert = UIAlertController(title: prompt, message: defaultText, preferredStyle: .alert)
+//        alert.addTextField { (textField: UITextField) -> Void in
+//            textField.textColor = UIColor.red
+//        }
+//        alert.addAction(UIAlertAction(title: "确定", style: .default, handler: { (_) -> Void in
+//            completionHandler(alert.textFields![0].text!)
+//        }))
+//        self.present(alert, animated: true, completion: nil)
+//    }
+//}
+//
diff --git a/LingQi/LingQi/UI/Base/YLprogressHUD.swift b/LingQi/LingQi/UI/Base/YLprogressHUD.swift
new file mode 100644 (file)
index 0000000..6655914
--- /dev/null
@@ -0,0 +1,80 @@
+//
+//  YLPro.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+import UIKit
+import SVProgressHUD
+
+class YLprogressHUD {
+    /// 显示自动消失的 HUD
+    static func showAutoHiden(_ text: String) {
+        SVProgressHUD.setMinimumDismissTimeInterval(1.5)
+        SVProgressHUD.setDefaultStyle(.dark)
+        SVProgressHUD.setDefaultMaskType(.clear)
+        SVProgressHUD.setContainerView(UIApplication.shared.keyWindow)
+        SVProgressHUD.show(UIImage(), status: text)
+    }
+    
+    /// 显示自动消失的 HUD,并在消失后执行回调
+    static func showAutoHiden(text: String, finished: @escaping () -> Void) {
+        showAutoHiden( text)
+        DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
+            finished()
+        }
+    }
+    static func showSuccess(finished: @escaping () -> Void) {
+        showAutoHiden( "请求成功!")
+        DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
+            finished()
+        }
+    }
+    
+    /// 显示"加载中..." HUD
+    static func showLoading() {
+        showWithStatus(status: "加载中...")
+    }
+    
+    /// 显示"上传中..." HUD
+    static func showUpLoading() {
+        showWithStatus(status: "上传中...")
+    }
+    
+    /// 隐藏 HUD
+    static func hidden() {
+        SVProgressHUD.dismiss()
+    }
+    
+    /// 获取当前顶层视图控制器
+    static func topViewController() -> UIViewController? {
+        guard let rootVC = UIApplication.shared.keyWindow?.rootViewController else {
+            return nil
+        }
+        return getTopViewController(from: rootVC)
+    }
+    
+    /// 递归获取顶层视图控制器
+    private static func getTopViewController(from vc: UIViewController) -> UIViewController {
+        if let navVC = vc as? UINavigationController {
+            return getTopViewController(from: navVC.visibleViewController ?? navVC)
+        } else if let tabVC = vc as? UITabBarController {
+            return getTopViewController(from: tabVC.selectedViewController ?? tabVC)
+        } else if let presentedVC = vc.presentedViewController {
+            return getTopViewController(from: presentedVC)
+        } else {
+            return vc
+        }
+    }
+    
+    /// 通用方法:显示带状态的 HUD
+    private static func showWithStatus(status: String) {
+        SVProgressHUD.show(withStatus: status)
+        SVProgressHUD.setDefaultStyle(.dark)
+        SVProgressHUD.setDefaultMaskType(.clear)
+        if let topVC = topViewController() {
+            SVProgressHUD.setContainerView(topVC.view)
+        }
+    }
+}
diff --git a/LingQi/LingQi/UI/Device/DeviceVC.swift b/LingQi/LingQi/UI/Device/DeviceVC.swift
new file mode 100644 (file)
index 0000000..77605a8
--- /dev/null
@@ -0,0 +1,18 @@
+//
+//  DeviceVC.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/10.
+//
+
+import Foundation
+import UIKit
+
+class DeviceVC:BaseVC{
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        self.navBar.title = "设备"
+        
+    }
+}
diff --git a/LingQi/LingQi/UI/Discover/DiscoverVC.swift b/LingQi/LingQi/UI/Discover/DiscoverVC.swift
new file mode 100644 (file)
index 0000000..c44b461
--- /dev/null
@@ -0,0 +1,18 @@
+//
+//  DeviceVC.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/10.
+//
+
+import Foundation
+import UIKit
+
+class DiscoverVC:BaseVC{
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        self.navBar.title = "发现"
+        
+    }
+}
diff --git a/LingQi/LingQi/UI/Home/HomeVC.swift b/LingQi/LingQi/UI/Home/HomeVC.swift
new file mode 100644 (file)
index 0000000..af098e7
--- /dev/null
@@ -0,0 +1,46 @@
+//
+//  HomeVC.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/3.
+//
+
+import UIKit
+
+class HomeVC:BaseVC{
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        self.navBar.title = "首页"
+        
+        self.navBar.rightView.setTitle("more", for: .normal)
+    }
+    
+    override func navRightViewTapped() {
+        let v = BasePickerView()
+        v.setupData(["2","3","4","5","6","7","8"])
+        v.selectedIndex(4)
+        v.show(animate: true)
+        return
+    }
+    
+    @objc func addDeviceAction(){
+        let vc = ScanDeviceVC()
+        self.navigationController?.pushViewController(vc, animated: true)
+    }
+    @objc func saveAction(){
+//        LogManager.instance.add("保存")
+//        LogManager.instance.saveToFile()
+
+//        SVProgressHUD.showLoading()
+//        HttpClient.instance.request(CommomApi.login(userName: "")) { (model:ResponseBaseModel, res) in
+//            if model.isSuccess{
+////                SVProgressHUD.show(withStatus: "请求成功")
+//            }
+//            else{
+////                SVProgressHUD.show(withStatus: "请求失败")
+//            }
+//        }
+    }
+}
+
diff --git a/LingQi/LingQi/UI/Mine/Login/AgreeView.swift b/LingQi/LingQi/UI/Mine/Login/AgreeView.swift
new file mode 100644 (file)
index 0000000..ca5ccbb
--- /dev/null
@@ -0,0 +1,66 @@
+//
+//  AgreeView.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+import UIKit
+class AgreeView: BaseView {
+     let agreeBtn = UIButton()
+     let agreeTitle = UILabel()
+     let agreeValue = UILabel()
+    override func setupViews() {
+        agreeBtn.do { (v) in
+            v.contentMode = .center
+            v.setImage(UIImage(named: "select_normal"), for: .normal)
+            v.setImage(UIImage(named: "select_selected"), for: .selected)
+            v.addTarget(self, action: #selector(agreeBtnAction), for: .touchUpInside)
+        }
+        agreeTitle.do { (v) in
+            v.textColor = .white.withAlphaComponent(0.8)
+            v.font = .medium(14)
+            v.textAlignment = .left
+            v.text = "登录即代表同意"
+        }
+        agreeValue.do { (v) in
+            v.textColor = .color(.theme)
+            v.font = .medium(14)
+            v.textAlignment = .left
+            v.text = " 《用户协议》"
+            v.add(target: self, action: #selector(agreementButtonAction))
+        }
+        addSubviews([agreeBtn,agreeTitle,agreeValue])
+    }
+    override func setupLayout() {
+        agreeBtn.snp.makeConstraints { (m) in
+            m.left.top.equalToSuperview()
+            m.height.equalTo(30)
+            m.width.equalTo(30)
+        }
+        agreeTitle.snp.makeConstraints { (m) in
+            m.left.equalTo(agreeBtn.snp.right)
+            m.height.equalToSuperview()
+            m.centerY.equalTo(agreeBtn)
+        }
+        agreeValue.snp.makeConstraints { (m) in
+            m.left.equalTo(agreeTitle.snp.right)
+            m.centerY.equalTo(agreeBtn)
+            m.right.equalToSuperview()
+        }
+    }
+    @objc func agreeBtnAction(){
+        agreeBtn.isSelected = !agreeBtn.isSelected
+    }
+    @objc func agreementButtonAction(){
+        
+    }
+}
+
+extension UILabel{
+    func add(target: Any?, action: Selector?){
+        let tap = UITapGestureRecognizer(target: target, action: action)
+        self.addGestureRecognizer(tap)
+        self.isUserInteractionEnabled = true
+    }
+}
diff --git a/LingQi/LingQi/UI/Mine/Login/CodeView.swift b/LingQi/LingQi/UI/Mine/Login/CodeView.swift
new file mode 100644 (file)
index 0000000..66e4dbe
--- /dev/null
@@ -0,0 +1,68 @@
+//
+//  CodeView.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+import UIKit
+class CodeView: BaseView {
+    let label = UILabel()
+    let inputBgView = UIView()
+    let textField = UITextField()
+    let codeButton = YLTimerButton()
+    override func setupViews() {
+        backgroundColor = .clear
+        
+        label.do { v in
+            v.text = "验证码"
+            v.font = .medium(12)
+            v.textColor = .white.withAlphaComponent(0.8)
+        }
+        textField.do { v in
+            v.textColor = .white
+            v.keyboardType = .phonePad
+        }
+        codeButton.do { (v) in
+            v.maxCount = 20
+            v.label.textColor = .color(.theme)
+            v.backgroundColor = UIColor.white.withAlphaComponent(0.04)
+            v.layer.cornerRadius = 8
+            v.layer.masksToBounds = true
+        }
+        
+        inputBgView.backgroundColor = UIColor.white.withAlphaComponent(0.04)
+        inputBgView.layer.borderColor = UIColor.white.withAlphaComponent(0.1).cgColor
+        inputBgView.layer.borderWidth = 0.5
+        inputBgView.layer.cornerRadius = 12
+        inputBgView.layer.masksToBounds = true
+        
+        addSubviews([label,inputBgView])
+        inputBgView.addSubviews([textField,codeButton])
+    }
+    override func setupLayout() {
+        label.snp.makeConstraints { make in
+            make.left.right.equalToSuperview().inset(15)
+            make.top.equalToSuperview()
+            make.height.equalTo(30)
+        }
+        inputBgView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview()
+            make.top.equalToSuperview().inset(30)
+            make.height.equalTo(52)
+            make.bottom.equalToSuperview()
+        }
+        textField.snp.makeConstraints { make in
+            make.left.equalToSuperview().inset(15)
+            make.right.equalToSuperview().inset(120)
+            make.top.bottom.equalToSuperview()
+        }
+        codeButton.snp.makeConstraints { (m) in
+            m.centerY.equalTo(textField)
+            m.right.equalToSuperview().inset(15)
+            m.width.equalTo(100)
+            m.height.equalTo(40)
+        }
+    }
+
+}
diff --git a/LingQi/LingQi/UI/Mine/Login/LoginVC.swift b/LingQi/LingQi/UI/Mine/Login/LoginVC.swift
new file mode 100644 (file)
index 0000000..59cc6d1
--- /dev/null
@@ -0,0 +1,105 @@
+//
+//  LoginVC.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+import UIKit
+
+class LoginVC:BaseVC{
+    let bgView = UIImageView()
+    let logoView = UIImageView()
+    let phoneView = PhoneView()
+    let codeView = CodeView()
+    let btn = CustomButton()
+    let agreeView  = AgreeView()
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+    }
+    override func setupViews(){
+        self.navBar.title = "账号登录"
+        view.backgroundColor = .rgb(0x11131E)
+        bgView.image = UIImage(named: "login_cover")
+        logoView.image = UIImage(named: "login_logo")
+        
+        phoneView.do { v in
+            v.textField.text = "13480939445"
+        }
+        codeView.do { v in
+            v.codeButton.addTarget(self, action: #selector(codeButtonAction), for: .touchUpInside)
+        }
+        
+        btn.set(title: "登录", target: self, action: #selector(loginAction))
+        
+        view.addSubviews([bgView,logoView,phoneView,codeView,btn,agreeView])
+        navBar.backgroundColor = .clear
+        view.bringSubviewToFront(navBar)
+    }
+    override func setupLayout(){
+        bgView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+        logoView.snp.makeConstraints { make in
+            make.width.equalTo(203)
+            make.height.equalTo(86)
+            make.top.equalTo(kNavBtm + 40)
+            make.centerX.equalToSuperview()
+        }
+        phoneView.snp.makeConstraints { make in
+            make.top.equalTo(logoView.snp.bottom).offset(60)
+            make.left.right.equalToSuperview().inset(15)
+        }
+        codeView.snp.makeConstraints { make in
+            make.top.equalTo(phoneView.snp.bottom).offset(10)
+            make.left.right.equalToSuperview().inset(15)
+        }
+        btn.snp.makeConstraints { make in
+            make.top.equalTo(codeView.snp.bottom).offset(30)
+            make.left.right.equalToSuperview().inset(15)
+            make.height.equalTo(52)
+        }
+        agreeView.snp.makeConstraints { make in
+            make.bottom.equalToSuperview().inset(62)
+            make.centerX.equalToSuperview()
+            make.height.equalTo(30)
+        }
+    }
+
+}
+
+extension LoginVC{
+    @objc func codeButtonAction(){
+        guard let text = phoneView.textField.text else{
+            YLprogressHUD.showAutoHiden("请输入正确的手机号码")
+            return
+        }
+        YLprogressHUD.showLoading()
+        LoginVM.sendCode(phone: text) { [weak self] (model) in
+            if model.isSuccess{
+                self?.codeView.codeButton.start()
+            }
+            YLprogressHUD.showAutoHiden(model.msg)
+        }
+    }
+    @objc func loginAction(){
+        guard let pohne = phoneView.textField.text else{
+            YLprogressHUD.showAutoHiden("请输入正确的手机号码")
+            return
+        }
+        guard let  code = codeView.textField.text else{
+            YLprogressHUD.showAutoHiden("请输入正确的验证码")
+            return
+        }
+        YLprogressHUD.showLoading()
+        LoginVM.login(phone: pohne, code: code) {[weak self] result in
+            if result.isSuccess{
+                YLprogressHUD.showSuccess {
+                    self?.view.window?.rootViewController = BaseTC()
+                }
+            }
+            YLprogressHUD.showAutoHiden(result.msg)
+        }
+    }
+}
diff --git a/LingQi/LingQi/UI/Mine/Login/LoginVM.swift b/LingQi/LingQi/UI/Mine/Login/LoginVM.swift
new file mode 100644 (file)
index 0000000..7f85862
--- /dev/null
@@ -0,0 +1,27 @@
+//
+//  LoginVM.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+class LoginModel:ResponseBaseModel {
+     var data:String = ""
+}
+
+
+class LoginVM:BaseVM{
+    static public func sendCode(phone:String, completion:@escaping (_ result:ResponseBaseModel) ->Void) {
+        HttpClient.instance.request(CommomApi.sms(phone: phone)) { (model:ResponseBaseModel, res) in
+            completion(model)
+        }
+    }
+    static public func login(phone:String,code:String, completion:@escaping (_ result:LoginModel) ->Void) {
+        HttpClient.instance.request(CommomApi.login(phone: phone,code: code)) { (model:LoginModel, res) in
+            if model.isSuccess{
+                UserModel.shared.token = model.data
+            }
+            completion(model)
+        }
+    }
+}
diff --git a/LingQi/LingQi/UI/Mine/Login/PhoneView.swift b/LingQi/LingQi/UI/Mine/Login/PhoneView.swift
new file mode 100644 (file)
index 0000000..42525b6
--- /dev/null
@@ -0,0 +1,51 @@
+//
+//  Untitled.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+import UIKit
+class PhoneView: BaseView {
+    let label = UILabel()
+    let inputBgView = UIView()
+    let textField = UITextField()
+    override func setupViews() {
+        backgroundColor = .clear
+        
+        label.do { v in
+            v.text = "手机号"
+            v.font = .medium(12)
+            v.textColor = .white.withAlphaComponent(0.8)
+        }
+        textField.do { v in
+            v.textColor = .white
+            v.keyboardType = .phonePad
+        }
+        
+        inputBgView.backgroundColor = UIColor.white.withAlphaComponent(0.04)
+        inputBgView.layer.borderColor = UIColor.white.withAlphaComponent(0.1).cgColor
+        inputBgView.layer.borderWidth = 0.5
+        inputBgView.layer.cornerRadius = 12
+        inputBgView.layer.masksToBounds = true
+        
+        addSubviews([label,inputBgView])
+        inputBgView.addSubview(textField)
+    }
+    override func setupLayout() {
+        label.snp.makeConstraints { make in
+            make.left.right.equalToSuperview().inset(15)
+            make.top.equalToSuperview()
+            make.height.equalTo(30)
+        }
+        inputBgView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview()
+            make.top.equalToSuperview().inset(30)
+            make.height.equalTo(52)
+            make.bottom.equalToSuperview()
+        }
+        textField.snp.makeConstraints { make in
+            make.left.right.equalToSuperview().inset(15)
+            make.top.bottom.equalToSuperview()
+        }
+    }
+}
diff --git a/LingQi/LingQi/UI/Mine/Login/UserModel.swift b/LingQi/LingQi/UI/Mine/Login/UserModel.swift
new file mode 100644 (file)
index 0000000..ac30160
--- /dev/null
@@ -0,0 +1,18 @@
+//
+//  UserModel.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+
+
+
+
+class UserModel {
+    static let shared = UserModel()
+    var token:String?
+    var isLogin:Bool{
+        return token != nil
+    }
+}
diff --git a/LingQi/LingQi/UI/Mine/Root/MineCell.swift b/LingQi/LingQi/UI/Mine/Root/MineCell.swift
new file mode 100644 (file)
index 0000000..d39f082
--- /dev/null
@@ -0,0 +1,109 @@
+//
+//  MineCell.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+import UIKit
+
+public enum MineCellType: Int {
+    case deviceList
+    case service
+    case product
+    
+    var title:String{
+        switch self {
+        case .deviceList:
+            return "设备列表"
+        case .service:
+            return "配额服务"
+        case .product:
+            return "产品说明"
+            
+        }
+    }
+    var icon:UIImage?{
+        switch self {
+        case .deviceList:
+            return UIImage(named: "mine_cell_device")
+        case .service:
+            return UIImage(named: "mine_cell_service")
+        case .product:
+            return UIImage(named: "mine_cell_product")
+        }
+    }
+}
+
+
+class MineCell: BaseTableViewCell {
+    let icon = UIImageView()
+    let titleLabel = UILabel()
+    let nextIcon = UIImageView()
+    let line = UIView()
+    
+    var type:MineCellType = .deviceList{
+        didSet{
+            icon.image = type.icon
+            titleLabel.text = type.title
+//            if type == .order {
+//                bgView.yc.setCorners(withRoundedRect: CGRect(x: 0, y: 0, width: kScreenWid - 24.fitR, height: 48.fitR), roundingCorners: [.topLeft,.topRight], cornerRadii: CGSize(width: 4.fitR, height: 4.fitR))
+//            }
+//            else if type == .set {
+//                bgView.yc.setCorners(withRoundedRect: CGRect(x: 0, y: 0, width: kScreenWid - 24.fitR, height: 48.fitR), roundingCorners: [.bottomLeft,.bottomRight], cornerRadii: CGSize(width: 4.fitR, height: 4.fitR))
+//            }
+//            else{
+//                bgView.layer.cornerRadius = 0
+//            }
+        }
+    }
+    
+    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+        super.init(style: style, reuseIdentifier: reuseIdentifier)
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    override func setupViews() {
+        contentView.addSubviews([icon,titleLabel,nextIcon,line])
+        backgroundColor = .clear
+        contentView.backgroundColor = .clear
+        selectionStyle = .none
+        line.do { (v) in
+            v.backgroundColor = .color(.separateLine)
+        }
+        titleLabel.do { (v) in
+            v.textColor = .white
+            v.font = .medium(16)
+            v.textAlignment = .left
+        }
+        nextIcon.image = UIImage(named: "arrow_next")
+    }
+
+    override func setupLayout() {
+        icon.snp.makeConstraints { (m) in
+            m.width.equalTo(24.fitR)
+            m.height.equalTo(24.fitR)
+            m.left.equalToSuperview().inset(15.fitR)
+            m.centerY.equalToSuperview()
+        }
+        nextIcon.snp.makeConstraints { (m) in
+            m.width.equalTo(20)
+            m.height.equalTo(20)
+            m.right.equalToSuperview().inset(15)
+            m.centerY.equalToSuperview()
+        }
+        titleLabel.snp.makeConstraints { (m) in
+            m.centerY.equalTo(icon)
+            m.left.equalTo(icon.snp.right).offset(6)
+            m.height.equalToSuperview()
+        }
+        line.snp.makeConstraints { (m) in
+            m.left.right.equalToSuperview().inset(15)
+            m.bottom.equalToSuperview()
+            m.height.equalTo(0.5)
+        }
+    }
+}
+
diff --git a/LingQi/LingQi/UI/Mine/Root/MineHeaderView.swift b/LingQi/LingQi/UI/Mine/Root/MineHeaderView.swift
new file mode 100644 (file)
index 0000000..c92d6c6
--- /dev/null
@@ -0,0 +1,30 @@
+//
+//  MineHeaderView.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+import UIKit
+class MineHeaderView: BaseView {
+    let userView = MineUserInfoView()
+    let orderView = MineOrderView()
+
+    
+    override func setupViews() {
+        backgroundColor = .clear
+        addSubviews([userView,orderView])
+    }
+    override func setupLayout() {
+        userView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview().inset(15)
+            make.top.equalToSuperview()
+            make.height.equalTo(120)
+        }
+        orderView.snp.makeConstraints { make in
+            make.left.right.equalToSuperview().inset(15)
+            make.top.equalTo(userView.snp.bottom).offset(20)
+            make.height.equalTo(140)
+        }
+    }
+}
diff --git a/LingQi/LingQi/UI/Mine/Root/MineNavBar.swift b/LingQi/LingQi/UI/Mine/Root/MineNavBar.swift
new file mode 100644 (file)
index 0000000..5fc4a30
--- /dev/null
@@ -0,0 +1,57 @@
+//
+//  MineNavBar.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+import UIKit
+class MineNavBar: BaseView {
+    let titleLabel = UILabel()
+    let messageBtn = UIButton()
+    let setBtn = UIButton()
+    
+    override func setupViews() {
+        backgroundColor = .color(.bgColor)
+        addSubviews([titleLabel,messageBtn,setBtn])
+        
+        titleLabel.do { v in
+            v.text = "我的"
+            v.font = .medium(18)
+            v.textColor = .white
+        }
+        setBtn.do { v in
+            v.setImage(UIImage(named: "mine_set"), for: .normal)
+            v.addTarget(self, action: #selector(setAction), for: .touchUpInside)
+        }
+        messageBtn.do { v in
+            v.setImage(UIImage(named: "mine_msg"), for: .normal)
+            v.addTarget(self, action: #selector(messageAction), for: .touchUpInside)
+        }
+    }
+    override func setupLayout() {
+        titleLabel.snp.makeConstraints { make in
+            make.left.equalToSuperview().inset(15)
+            make.bottom.equalToSuperview().inset(15)
+        }
+        setBtn.snp.makeConstraints { make in
+            make.centerY.equalTo(titleLabel)
+            make.right.equalToSuperview().inset(15)
+            make.size.equalTo(30)
+        }
+        messageBtn.snp.makeConstraints { make in
+            make.centerY.equalTo(titleLabel)
+            make.right.equalTo(setBtn.snp.left).offset(-15)
+            make.size.equalTo(30)
+        }
+    }
+    
+    @objc func messageAction(){
+        
+    }
+    @objc func setAction(){
+        let vc = UserInfoVC()
+        let topVC = App.shared.topVC()
+        topVC?.navigationController?.pushViewController(vc, animated: true)
+    }
+}
diff --git a/LingQi/LingQi/UI/Mine/Root/MineOrderView.swift b/LingQi/LingQi/UI/Mine/Root/MineOrderView.swift
new file mode 100644 (file)
index 0000000..1deb58d
--- /dev/null
@@ -0,0 +1,18 @@
+//
+//  MineOrderView.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+import UIKit
+class MineOrderView: BaseView {
+
+    override func setupViews() {
+        backgroundColor = .white
+    }
+    override func setupLayout() {
+
+    }
+    
+}
diff --git a/LingQi/LingQi/UI/Mine/Root/MineUserInfoView.swift b/LingQi/LingQi/UI/Mine/Root/MineUserInfoView.swift
new file mode 100644 (file)
index 0000000..4bce1f7
--- /dev/null
@@ -0,0 +1,19 @@
+//
+//  MineUserInfoView.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+import UIKit
+class MineUserInfoView: BaseView {
+    
+    override func setupViews() {
+        backgroundColor = .white
+        
+    }
+    override func setupLayout() {
+        
+    }
+    
+}
diff --git a/LingQi/LingQi/UI/Mine/Root/MineVC.swift b/LingQi/LingQi/UI/Mine/Root/MineVC.swift
new file mode 100644 (file)
index 0000000..cf3b645
--- /dev/null
@@ -0,0 +1,57 @@
+//
+//  SetVC.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/3.
+//
+
+import UIKit
+class MineVC: BaseVC{
+    let tableView = UITableView(frame: .zero, style: .plain)
+    let list:[MineCellType] = [.deviceList,.service,.product,]
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        // Do any additional setup after loading the view.
+    }
+    override func setupViews() {
+        self.navBar.title = "我的"
+        tableView.do { v in
+            v.backgroundColor = .color(.bgColor)
+            v.delegate = self
+            v.dataSource = self
+            v.rowHeight = 68
+            v.register(MineCell.self, forCellReuseIdentifier: MineCell.reuseID)
+            v.tableHeaderView = MineHeaderView(frame: CGRect(x: 0, y: 0, width: kScreenWid, height: 280))
+        }
+        view.addSubview(tableView)
+        
+        let bar = MineNavBar(frame: navBar.frame)
+        navBar.addSubview(bar)
+    }
+    override func setupLayout() {
+        tableView.snp.makeConstraints { make in
+            make.left.right.bottom.equalToSuperview()
+            make.top.equalTo(kNavBtm)
+        }
+    }
+}
+
+extension MineVC:UITableViewDelegate,UITableViewDataSource {
+    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
+        return 60
+    }
+    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        return list.count
+    }
+    
+    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        let cell = MineCell.cell(withTableView: tableView, indexPath: indexPath)
+        cell.type = list[indexPath.row]
+        return cell
+    }
+    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        let data = list[indexPath.row]
+
+    }
+}
diff --git a/LingQi/LingQi/UI/Mine/UserInfo/UserInfoCell.swift b/LingQi/LingQi/UI/Mine/UserInfo/UserInfoCell.swift
new file mode 100644 (file)
index 0000000..a8d7cdf
--- /dev/null
@@ -0,0 +1,195 @@
+//
+//  UserInfoCell.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+import UIKit
+
+public enum UserInfoCellType: Int {
+    case avatar
+    case nickName
+    case gender
+    case phone
+    case password
+    case deregister
+    
+    var title:String{
+        switch self {
+        case .avatar:
+            return "头像"
+        case .nickName:
+            return "昵称"
+        case .gender:
+            return "性别"
+        case .phone:
+            return "手机号"
+        case .password:
+            return "密码"
+        case .deregister:
+            return "注销账号"
+        }
+    }
+    
+}
+
+
+class UserInfoCell: BaseTableViewCell {
+    let bgView = UIView()
+    let icon = UIImageView()
+    let titleLabel = UILabel()
+    let valueLabel = UILabel()
+    let nextIcon = UIImageView()
+    
+    var type:UserInfoCellType = .avatar{
+        didSet{
+            titleLabel.text = type.title
+            valueLabel.text = "1111"
+        }
+    }
+    
+    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+        super.init(style: style, reuseIdentifier: reuseIdentifier)
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    override func setupViews() {
+        contentView.addSubview(bgView)
+        bgView.addSubviews([titleLabel,icon,valueLabel,nextIcon])
+        
+        backgroundColor = .clear
+        contentView.backgroundColor = .clear
+        selectionStyle = .none
+        bgView.do { v in
+            v.backgroundColor = UIColor.white.withAlphaComponent(0.04)
+            v.layer.borderColor = UIColor.white.withAlphaComponent(0.1).cgColor
+            v.layer.borderWidth = 0.5
+            v.layer.cornerRadius = 12
+            v.layer.masksToBounds = true
+        }
+        titleLabel.do { (v) in
+            v.textColor = .white
+            v.font = .medium(16)
+            v.textAlignment = .left
+        }
+        valueLabel.do { (v) in
+            v.textColor = .white.withAlphaComponent(0.8)
+            v.font = .medium(14)
+            v.textAlignment = .right
+        }
+        nextIcon.image = UIImage(named: "arrow_next")
+    }
+    
+    override func setupLayout() {
+        bgView.snp.makeConstraints { (m) in
+            m.left.right.equalToSuperview().inset(15)
+            m.top.equalToSuperview().inset(6)
+            m.bottom.equalToSuperview().inset(6)
+            m.height.equalTo(52)
+        }
+        nextIcon.snp.makeConstraints { (m) in
+            m.width.equalTo(20)
+            m.height.equalTo(20)
+            m.right.equalToSuperview().inset(15)
+            m.centerY.equalToSuperview()
+        }
+        icon.snp.makeConstraints { (m) in
+            m.width.equalTo(46)
+            m.height.equalTo(46)
+            m.right.equalToSuperview().inset(40)
+            m.centerY.equalToSuperview()
+        }
+        titleLabel.snp.makeConstraints { (m) in
+            m.centerY.equalTo(icon)
+            m.left.equalToSuperview().inset(15)
+            m.height.equalToSuperview()
+        }
+        valueLabel.snp.makeConstraints { (m) in
+            m.centerY.equalTo(icon)
+            m.right.equalToSuperview().inset(40)
+            m.height.equalToSuperview()
+        }
+
+    }
+}
+
+class UserInfoImageCell: BaseTableViewCell {
+    let bgView = UIView()
+    let icon = UIImageView()
+    let titleLabel = UILabel()
+    let nextIcon = UIImageView()
+    let imgPicker = ImagePickerManager()
+
+    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+        super.init(style: style, reuseIdentifier: reuseIdentifier)
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    override func setupViews() {
+        contentView.addSubview(bgView)
+        bgView.addSubviews([titleLabel,icon,nextIcon])
+        
+        backgroundColor = .clear
+        contentView.backgroundColor = .clear
+        selectionStyle = .none
+        bgView.do { v in
+            v.backgroundColor = UIColor.white.withAlphaComponent(0.04)
+            v.layer.borderColor = UIColor.white.withAlphaComponent(0.1).cgColor
+            v.layer.borderWidth = 0.5
+            v.layer.cornerRadius = 12
+            v.layer.masksToBounds = true
+            v.yc.addTap(target: self, action:#selector(pickImageAction ))
+        }
+        titleLabel.do { (v) in
+            v.textColor = .white
+            v.font = .medium(16)
+            v.textAlignment = .left
+            v.text = "头像"
+        }
+        icon.do { v in
+            v.yc.setCornerRadius(23)
+            v.backgroundColor = .white.withAlphaComponent(0.5)
+        }
+        nextIcon.image = UIImage(named: "arrow_next")
+    }
+    
+    override func setupLayout() {
+        bgView.snp.makeConstraints { (m) in
+            m.left.right.equalToSuperview().inset(15)
+            m.top.equalToSuperview().inset(6)
+            m.bottom.equalToSuperview().inset(6)
+            m.height.equalTo(72)
+        }
+        nextIcon.snp.makeConstraints { (m) in
+            m.width.equalTo(20)
+            m.height.equalTo(20)
+            m.right.equalToSuperview().inset(15)
+            m.centerY.equalToSuperview()
+        }
+        icon.snp.makeConstraints { (m) in
+            m.width.equalTo(46)
+            m.height.equalTo(46)
+            m.right.equalToSuperview().inset(40)
+            m.centerY.equalToSuperview()
+        }
+        titleLabel.snp.makeConstraints { (m) in
+            m.centerY.equalTo(icon)
+            m.left.equalToSuperview().inset(15)
+            m.height.equalToSuperview()
+        }
+        
+    }
+    
+    @objc func pickImageAction() -> Void {
+        imgPicker.showImagePicker(from: App.shared.topVC()) {[weak self] image in
+            guard let self = self else { return  }
+            icon.image = image
+        }
+    }
+}
+
diff --git a/LingQi/LingQi/UI/Mine/UserInfo/UserInfoSectionHeader.swift b/LingQi/LingQi/UI/Mine/UserInfo/UserInfoSectionHeader.swift
new file mode 100644 (file)
index 0000000..1f28c1e
--- /dev/null
@@ -0,0 +1,28 @@
+//
+//  UserInfoSectionHeader.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/31.
+//
+
+
+class UserInfoSectionHeader: BaseTableViewSetionHeader {
+    let titleLabel = UILabel()
+    override func setupViews() {
+        contentView.backgroundColor = .color(.bgColor)
+        contentView.addSubview(titleLabel)
+        titleLabel.do { (v) in
+            v.textColor = .white.withAlphaComponent(0.8)
+            v.font = .medium(16)
+            v.textAlignment = .left
+        }
+    }
+    
+    override func setupLayout() {
+        titleLabel.snp.makeConstraints { (m) in
+            m.top.equalToSuperview().inset(10)
+            m.bottom.equalToSuperview()
+            m.left.equalToSuperview().inset(30)
+        }
+    }
+}
diff --git a/LingQi/LingQi/UI/Mine/UserInfo/UserInfoVC.swift b/LingQi/LingQi/UI/Mine/UserInfo/UserInfoVC.swift
new file mode 100644 (file)
index 0000000..142199f
--- /dev/null
@@ -0,0 +1,82 @@
+//
+//  UserInfoVC.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+import UIKit
+class UserInfoVC: BaseVC{
+    let tableView = UITableView(frame: .zero, style: .plain)
+    let list:[(title:String,list:[UserInfoCellType])] = [("编辑资料",[.avatar,.nickName,.gender]),("账号与安全",[.phone,.password,.deregister])]
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        // Do any additional setup after loading the view.
+    }
+    override func setupViews() {
+        self.navBar.title = "用户信息"
+        tableView.do { v in
+            v.backgroundColor = .color(.bgColor)
+            v.delegate = self
+            v.dataSource = self
+            v.estimatedRowHeight = 52
+            v.sectionHeaderHeight = 52
+            v.sectionFooterHeight = 0.1
+            v.register(UserInfoCell.self, forCellReuseIdentifier: UserInfoCell.reuseID)
+            v.register(UserInfoImageCell.self, forCellReuseIdentifier: UserInfoImageCell.reuseID)
+            
+            v.register(UserInfoSectionHeader.self, forHeaderFooterViewReuseIdentifier: UserInfoSectionHeader.reuseID)
+            v.register(BaseTableViewSetionHeader.self, forHeaderFooterViewReuseIdentifier: BaseTableViewSetionHeader.reuseID)
+        }
+        
+        let footView = UIView(frame: CGRect(x: 0, y: 0, width: kScreenWid, height: 200))
+        let btn = CustomButton(frame: CGRect(x: 15, y: 80, width: kScreenWid - 30, height: 52))
+        btn.set(title: "退出登录", bgColor: .white.withAlphaComponent(0.04), target: self, action: #selector(logoutAction))
+        footView.addSubview(btn)
+        tableView.tableFooterView = footView
+        
+        view.addSubview(tableView)
+    }
+    override func setupLayout() {
+        tableView.snp.makeConstraints { make in
+            make.left.right.bottom.equalToSuperview()
+            make.top.equalTo(kNavBtm)
+        }
+    }
+}
+
+extension UserInfoVC:UITableViewDelegate,UITableViewDataSource {
+    func numberOfSections(in tableView: UITableView) -> Int {
+        return list.count
+    }
+    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        return list[section].list.count
+    }
+    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
+        let view = UserInfoSectionHeader.header(withTableView: tableView)
+        view.titleLabel.text = list[section].title
+        return view
+    }
+    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        let type = list[indexPath.section].list[indexPath.row]
+        if type == .avatar {
+            let cell = UserInfoImageCell.cell(withTableView: tableView, indexPath: indexPath)
+            return cell
+        }
+        else{
+            let cell = UserInfoCell.cell(withTableView: tableView, indexPath: indexPath)
+            cell.type = type
+            return cell
+        }
+    }
+    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        let data = list[indexPath.section].list[indexPath.row]
+    }
+}
+
+extension UserInfoVC{
+    @objc func logoutAction(){
+        
+    }
+}
diff --git a/LingQi/LingQi/UI/Scan/DeviceCell.swift b/LingQi/LingQi/UI/Scan/DeviceCell.swift
new file mode 100644 (file)
index 0000000..36915eb
--- /dev/null
@@ -0,0 +1,60 @@
+//
+//  DeviceCell.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/3.
+//
+
+import UIKit
+import SnapKit
+
+class DeviceCell: BaseTableViewCell {
+    
+    var titleLabel = UILabel()
+    var valueLabel = UILabel()
+    
+    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+        super.init(style: style, reuseIdentifier: reuseIdentifier)
+        setupView()
+        setupStyle()
+        setupLayout()
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    func setupView(){
+        contentView.addSubview(titleLabel)
+        contentView.addSubview(valueLabel)
+        
+    }
+    func setupStyle(){
+        titleLabel.do { v in
+            v.textColor = .color(.primary)
+            v.font = UIFont.systemFont(ofSize: 16)
+        }
+        valueLabel.do { v in
+            v.textColor = .color(.secondary)
+            v.font = UIFont.systemFont(ofSize: 14)
+        }
+        
+    }
+    override func setupLayout(){
+        titleLabel.snp.makeConstraints { make in
+            make.left.equalToSuperview().inset(20)
+            make.centerY.equalToSuperview()
+        }
+        valueLabel.snp.makeConstraints({ make in
+            make.right.equalToSuperview().inset(20)
+            make.centerY.equalToSuperview()
+        })
+    }
+    
+    var model:ScanModel = ScanModel(){
+        didSet{
+            titleLabel.text = model.peripheral.name
+            valueLabel.text = "\(model.peripheral.rssi)"
+        }
+    }
+}
diff --git a/LingQi/LingQi/UI/Scan/ScanDeviceVC.swift b/LingQi/LingQi/UI/Scan/ScanDeviceVC.swift
new file mode 100644 (file)
index 0000000..5427420
--- /dev/null
@@ -0,0 +1,103 @@
+//
+//  ScanDeviceVC.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/3.
+//
+
+import UIKit
+import SnapKit
+import MJRefresh
+class ScanDeviceVC: BaseVC {
+    var viewModel = BlueToothViewModel.shareModel
+
+    lazy var tableview :UITableView = {
+        let table = UITableView(frame: self.view.bounds, style: .plain)
+        return table
+    }()
+
+
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        // Do any additional setup after loading the view.
+
+        setupView()
+        setupLayout()
+        setupStyle()
+        setupViewModel()
+//        refreshAction()
+    }
+    override func viewDidAppear(_ animated: Bool) {
+        super.viewDidAppear(animated)
+//        self.tableview.mj_header?.endRefreshing()
+//        if viewModel.selectedPeripheral == nil {
+//            return
+//        }
+//        if viewModel.dataList.count > 0{
+//            viewModel.sendFinishShishiShuJuXiang()
+//        }
+//        else{
+//            YLProgressHUD.instance.showLoading()
+//            viewModel.reRequestShishiShuJuXiang()
+//        }
+//        viewModel.sendFailure = {[weak self] in
+//            self?.tableview.mj_header?.endRefreshing()
+//        }
+    }
+
+    func setupView(){
+        view.addSubview(tableview)
+    }
+    func setupStyle(){
+//        navBar.title = "tab_data"
+        tableview.do { v in
+            v.delegate = self
+            v.dataSource = self
+            v.rowHeight = 60
+            v.register(DeviceCell.self, forCellReuseIdentifier: DeviceCell.reuseID())
+            v.mj_header = MJRefreshNormalHeader(refreshingTarget: self, refreshingAction: #selector(refreshAction))
+        }
+    }
+    override func setupLayout() {
+        tableview.snp.makeConstraints { make in
+            make.top.equalToSuperview().inset(100)
+            make.left.right.bottom.equalToSuperview()
+        }
+    }
+    func setupViewModel(){
+        viewModel.deviceListDidChange = {[weak self] in
+            guard let self = self else { return  }
+            self.tableview.reloadData()
+            self.tableview.mj_header?.endRefreshing()
+        }
+    }
+    @objc func refreshAction(){
+//        if viewModel.selectedPeripheral == nil {
+//            self.tableview.mj_header?.endRefreshing()
+//            return
+//        }
+//        if viewModel.dataList.count > 0{
+//            viewModel.sendFinishShishiShuJuXiang()
+//        }
+//        else{
+//            viewModel.reRequestShishiShuJuXiang()
+//        }
+    }
+}
+extension ScanDeviceVC:UITableViewDelegate,UITableViewDataSource{
+    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        return viewModel.deviceList.count
+    }
+    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        let cell = DeviceCell.cell(withTableView: tableView, indexPath: indexPath)
+        cell.model = viewModel.deviceList[indexPath.row];
+        return cell
+    }
+
+    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        let model = viewModel.deviceList[indexPath.row]
+        viewModel.bluetooth.connect(peripheral: model.peripheral)
+    }
+}
+
diff --git a/LingQi/LingQi/UI/common/AgreeMentPopView.swift b/LingQi/LingQi/UI/common/AgreeMentPopView.swift
new file mode 100644 (file)
index 0000000..4742902
--- /dev/null
@@ -0,0 +1,142 @@
+//
+//  AgreeMentPopView.swift
+//  Magpie
+//
+//  Created by incar on 2024/1/11.
+//
+
+import UIKit
+
+class AgreeMentPopView: BasePresentView {
+    private let titleLabel = UILabel()
+    private let des = UILabel()
+    private let selectButton = UIButton()
+    private let privacyLabel = UILabel()
+    private let okButton = UIButton()
+    
+    init() {
+        super.init(contentHeight: 400.fitR)
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    override func setupSubView() {
+        super.setupSubView()
+        contentView.addSubview(titleLabel)
+        contentView.addSubview(des)
+        contentView.addSubview(selectButton)
+        contentView.addSubview(privacyLabel)
+        contentView.addSubview(okButton)
+    }
+    override func setupLayout() {
+        super.setupLayout()
+        titleLabel.snp.makeConstraints { (m) in
+            m.top.equalToSuperview().inset(25.fitR)
+            m.left.right.equalToSuperview()
+            m.height.greaterThanOrEqualTo(0)
+        }
+        des.snp.makeConstraints { (m) in
+            m.left.right.equalToSuperview().inset(20.fitR)
+            m.top.equalToSuperview().inset(67.fitR)
+        }
+        selectButton.snp.makeConstraints { (m) in
+            m.left.equalToSuperview().inset(20.fitR)
+            m.bottom.equalToSuperview().inset(96.fitR)
+            m.height.equalTo(15.fitR)
+            m.width.equalTo(15.fitR)
+        }
+        privacyLabel.snp.makeConstraints { (m) in
+            m.left.equalTo(selectButton.snp.right)
+            m.centerY.equalTo(selectButton)
+        }
+        okButton.snp.makeConstraints { (m) in
+            m.bottom.equalToSuperview().inset(30.fitR)
+            m.height.equalTo(44.fitR)
+            m.left.right.equalToSuperview().inset(25.fitR)
+        }
+    }
+    
+    override func setupStyle() {
+        super.setupStyle()
+        titleLabel.do { (v) in
+            v.textColor = .rgb(0x333333)
+            v.font = .semiBold(16)
+            v.textAlignment = .center
+            v.text = "诸葛驾到代运营协议说明"
+        }
+        des.do { (v) in
+            v.text = "1.用户通过诸葛驾到寻找到合适的驾校后,委托诸葛驾到负责撮合驾校学车的服务提供方,为用户代报名指定班型的学车服务,在代报名过程中提供驾校信息核验、学车权益守护、学车资金托管、代理结算等服务。具体服务内容由诸葛驾到根据实际情况提供,包括但不限于: (1) 作为用户的学车经纪人代表用户与驾校签约学车报名协议;(2)学车报名资金的托管; (3) 维护用户在驾校学车的约定权益;(4) 服务商收入结算和用户支付费用:具体金额以产生的统计数据为准;(5) 订单查询;2.用户通过诸葛驾到完成的学车报名信息以平台发布的相应信息为准,交易应签署《学车报名服务合同》。具体内容《学车报名服务合同》以约定为准,该合同文本格式由诸葛驾到平台的驾校提供,经诸葛驾到平台撮合,由用户与诸葛驾到平台的驾校直接签约。所有发给用户的通告及其他消息都可通过APP或者用户所提供的联系方式发送 。"
+            v.textAlignment = .left
+            v.numberOfLines = 0
+            v.font = .regular(12)
+            v.textColor = .rgb(0x666666)
+        }
+        selectButton.do { (v) in
+            v.yc.setBorder(width: 1.fitR, color: .rgb(0x999999), radius: 2.fitR)
+            v.setImage(nil, for: .normal)
+            v.addTarget(self, action: #selector(selectBtnAction), for: .touchUpInside)
+        }
+        privacyLabel.do { (v) in
+            v.text = "  已阅读同意协议说明"
+            v.textAlignment = .left
+            v.numberOfLines = 1
+            v.font = .regular(12)
+            v.textColor = .rgb(0x999999)
+            privacyLabel.yc.addTap(target: self, action: #selector(selectBtnAction))
+        }
+        okButton.do { (v) in
+            v.isEnabled = false
+            v.yc.addGardiendLayerWith(colors: [.red,.blue], frame: CGRect(x: 0, y: 0, width: kScreenWid - 50.fitR, height: 44.fitR), direction: .left2right)
+            v.setTitle("下一步", for: .normal)
+            v.setTitleColor(.white, for: .normal)
+            v.titleLabel?.font = .regular(15)
+            v.yc.setCornerRadius(22.fitR)
+            v.alpha = 0.5
+            v.addTarget(self, action: #selector(okButtonAction), for: .touchUpInside)
+            self.selectBtnAction()
+            
+        }
+    }
+    @objc func okButtonAction(){
+        //            self.okButtonTap?()
+        //            hide()
+        self.start2LoadData()
+    }
+    @objc func selectBtnAction(){
+        selectButton.isSelected = !selectButton.isSelected
+        if selectButton.isSelected {
+            selectButton.yc.setBorder(width: 1.fitR, color: .rgb(0x036AFF), radius: 2.fitR)
+            selectButton.setImage(UIImage(named: "agreement_selected"), for: .normal)
+            privacyLabel.textColor = .rgb(0x036AFF)
+            okButton.alpha = 1
+        }
+        else{
+            selectButton.yc.setBorder(width: 1.fitR, color: .rgb(0x999999), radius: 2.fitR)
+            selectButton.setImage(nil, for: .normal)
+            privacyLabel.textColor = .rgb(0x999999)
+            okButton.alpha = 0.5
+        }
+        okButton.isEnabled = selectButton.isSelected
+    }
+    
+    func start2LoadData(){
+        //            SVProgressHUD.showLoading()
+        //            SVProgressHUD.setContainerView(app.window)
+        //            self.vm.fetchClassDetail{[weak self] (model) in
+        //                guard let self = self else {return}
+        //                if model.isSuccess{
+        //                    SVProgressHUD.hidden()
+        //                    self.hide()
+        //                    let params = PayDetailVCParams(model:model.data)
+        //                    let vc = PayDetailVC(data: params)
+        //                    UIViewController.yc.currentNav?.pushViewController(vc, animated: true)
+        //                }
+        //                else{
+        //                    SVProgressHUD.showAutoHiden(model.msg)
+        //                }
+        //            }
+    }
+}
+
diff --git a/LingQi/LingQi/UI/common/CustomButton.swift b/LingQi/LingQi/UI/common/CustomButton.swift
new file mode 100644 (file)
index 0000000..1723ec1
--- /dev/null
@@ -0,0 +1,19 @@
+//
+//  CustomButton.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/30.
+//
+
+import UIKit
+class CustomButton: UIButton {
+    func set(title:String,bgColor:UIColor = .rgb(0x0245BC), target: Any?, action: Selector) {
+        setTitle(title, for: .normal)
+        setTitleColor(.white, for: .normal)
+        addTarget(target, action: action, for: .touchUpInside)
+        layer.cornerRadius = 12
+        layer.masksToBounds = true
+        titleLabel?.font = .systemFont(ofSize: 16)
+        backgroundColor = bgColor
+    }
+}
diff --git a/LingQi/LingQi/UI/common/ImagePickerManager.swift b/LingQi/LingQi/UI/common/ImagePickerManager.swift
new file mode 100644 (file)
index 0000000..d414d79
--- /dev/null
@@ -0,0 +1,142 @@
+//
+//  ImagePic.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/31.
+//
+
+////
+////  ImagePicker.swift
+////  BlueMagpie
+////
+////  Created by liangshi on 2025/7/8.
+////
+//
+
+import UIKit
+import TZImagePickerController
+import AVFoundation
+
+typealias ImagePickerCallback = (UIImage?) -> Void
+typealias VideoPickerCallback = (UIImage?, URL?, Error?) -> Void
+
+class ImagePickerManager: NSObject, TZImagePickerControllerDelegate {
+    
+    private var imageCallback: ImagePickerCallback?
+    private var videoCallback: VideoPickerCallback?
+    
+    // MARK: - 图片选择
+    func showImagePicker(from viewController: UIViewController, callback: @escaping ImagePickerCallback) {
+        self.imageCallback = callback
+        
+        let picker = TZImagePickerController(maxImagesCount: 1, delegate: self)
+        picker?.needCircleCrop = true
+        picker?.circleCropRadius = Int(UIScreen.main.bounds.size.width/2)
+        picker?.allowCrop = true
+        picker?.showSelectBtn = false
+        picker?.allowPickingOriginalPhoto = false
+        picker?.allowPickingVideo = false
+        picker?.allowPickingImage = true
+        picker?.modalPresentationStyle = .overFullScreen
+        viewController.present(picker!, animated: true, completion: nil)
+    }
+    
+    // MARK: - 视频选择
+    func showVideoPicker(from viewController: UIViewController, callback: @escaping VideoPickerCallback) {
+        self.videoCallback = callback
+        
+        let picker = TZImagePickerController(maxImagesCount: 1, delegate: self)
+        picker?.allowPickingImage = false
+        picker?.allowPickingVideo = true
+        picker?.allowPickingOriginalPhoto = false
+        picker?.showSelectBtn = false
+        picker?.allowPickingMultipleVideo = false
+        picker?.modalPresentationStyle = .overFullScreen
+        viewController.present(picker!, animated: true, completion: nil)
+    }
+    
+    // MARK: - 图片选择回调
+    func imagePickerController(_ picker: TZImagePickerController!, didFinishPickingPhotos photos: [UIImage]!, sourceAssets assets: [Any]!, isSelectOriginalPhoto: Bool) {
+        imageCallback?(photos?.first)
+        imageCallback = nil
+    }
+    
+    // MARK: - 视频选择回调
+    func imagePickerController(_ picker: TZImagePickerController!, didFinishPickingVideo coverImage: UIImage!, sourceAssets asset: PHAsset!) {
+        guard let asset = asset, asset.mediaType == .video else {
+            videoCallback?(coverImage, nil, nil)
+            videoCallback = nil
+            return
+        }
+        
+        // 请求视频URL
+        let options = PHVideoRequestOptions()
+        options.isNetworkAccessAllowed = true
+        options.deliveryMode = .automatic
+        
+        PHImageManager.default().requestAVAsset(forVideo: asset, options: options) { [weak self] avAsset, audioMix, info in
+            DispatchQueue.main.async {
+                guard let self = self, let avAsset = avAsset else {
+                    self?.videoCallback?(coverImage, nil, nil)
+                    self?.videoCallback = nil
+                    return
+                }
+                
+                // 转换视频为MP4格式
+                self.convertVideoToMP4(avAsset: avAsset) { [weak self] outputURL, error in
+                    self?.videoCallback?(coverImage, outputURL, error)
+                    self?.videoCallback = nil
+                }
+            }
+        }
+    }
+    
+    // MARK: - 视频格式转换
+    private func convertVideoToMP4(avAsset: AVAsset, completion: @escaping (URL?, Error?) -> Void) {
+        // 创建导出会话
+        guard let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetHighestQuality) else {
+            completion(nil, NSError(domain: "VideoExportError", code: 1, userInfo: [NSLocalizedDescriptionKey: "无法创建导出会话"]))
+            return
+        }
+        
+        // 检查是否支持导出为MP4格式
+        if !exportSession.supportedFileTypes.contains(.mp4) {
+            completion(nil, NSError(domain: "VideoExportError", code: 2, userInfo: [NSLocalizedDescriptionKey: "不支持导出为MP4格式"]))
+            return
+        }
+        
+        // 创建输出URL
+        let outputFileName = UUID().uuidString + ".mp4"
+        let outputURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(outputFileName)
+        
+        // 配置导出会话
+        exportSession.outputFileType = .mp4
+        exportSession.outputURL = outputURL
+        exportSession.shouldOptimizeForNetworkUse = true
+        
+        // 开始导出
+        exportSession.exportAsynchronously {
+            // 修复 DispatchQueue 调用问题
+            DispatchQueue.main.async {
+                switch exportSession.status {
+                case.completed:
+                    completion(outputURL, nil)
+                case.failed:
+                    completion(nil, exportSession.error)
+                case.cancelled:
+                    completion(nil, NSError(domain: "VideoExportError", code: 3, userInfo: [NSLocalizedDescriptionKey: "导出已取消"]))
+                default:
+                    completion(nil, NSError(domain: "VideoExportError", code: 4, userInfo: [NSLocalizedDescriptionKey: "导出状态未知"]))
+                }
+            }
+        }
+    }
+    
+    // MARK: - 取消选择
+    func tz_imagePickerControllerDidCancel(_ picker: TZImagePickerController!) {
+        imageCallback?(nil)
+        videoCallback?(nil, nil, nil)
+        imageCallback = nil
+        videoCallback = nil
+    }
+}
diff --git a/LingQi/LingQi/ViewController.swift b/LingQi/LingQi/ViewController.swift
new file mode 100644 (file)
index 0000000..88f2c7d
--- /dev/null
@@ -0,0 +1,19 @@
+//
+//  ViewController.swift
+//  LingQi
+//
+//  Created by liangshi on 2025/7/29.
+//
+
+import UIKit
+
+class ViewController: UIViewController {
+
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        // Do any additional setup after loading the view.
+    }
+
+
+}
+
diff --git a/LingQi/Podfile.lock b/LingQi/Podfile.lock
new file mode 100644 (file)
index 0000000..0317b18
--- /dev/null
@@ -0,0 +1,147 @@
+PODS:
+  - Alamofire (5.10.2)
+  - FDFullscreenPopGesture (1.1)
+  - HandyJSON (5.0.2)
+  - IQKeyboardCore (1.0.5)
+  - IQKeyboardManagerSwift (8.0.1):
+    - IQKeyboardManagerSwift/Appearance (= 8.0.1)
+    - IQKeyboardManagerSwift/Core (= 8.0.1)
+    - IQKeyboardManagerSwift/IQKeyboardReturnManager (= 8.0.1)
+    - IQKeyboardManagerSwift/IQKeyboardToolbarManager (= 8.0.1)
+    - IQKeyboardManagerSwift/IQTextView (= 8.0.1)
+    - IQKeyboardManagerSwift/Resign (= 8.0.1)
+  - IQKeyboardManagerSwift/Appearance (8.0.1):
+    - IQKeyboardManagerSwift/Core
+  - IQKeyboardManagerSwift/Core (8.0.1):
+    - IQKeyboardNotification
+    - IQTextInputViewNotification
+  - IQKeyboardManagerSwift/IQKeyboardReturnManager (8.0.1):
+    - IQKeyboardReturnManager
+  - IQKeyboardManagerSwift/IQKeyboardToolbarManager (8.0.1):
+    - IQKeyboardManagerSwift/Core
+    - IQKeyboardToolbarManager
+  - IQKeyboardManagerSwift/IQTextView (8.0.1):
+    - IQTextView
+  - IQKeyboardManagerSwift/Resign (8.0.1):
+    - IQKeyboardManagerSwift/Core
+  - IQKeyboardNotification (1.0.3)
+  - IQKeyboardReturnManager (1.0.4):
+    - IQKeyboardCore (= 1.0.5)
+  - IQKeyboardToolbar (1.1.1):
+    - IQKeyboardCore
+    - IQKeyboardToolbar/Core (= 1.1.1)
+  - IQKeyboardToolbar/Core (1.1.1):
+    - IQKeyboardCore
+    - IQKeyboardToolbar/Placeholderable
+  - IQKeyboardToolbar/Placeholderable (1.1.1):
+    - IQKeyboardCore
+  - IQKeyboardToolbarManager (1.1.3):
+    - IQKeyboardToolbar
+    - IQTextInputViewNotification
+  - IQTextInputViewNotification (1.0.8):
+    - IQKeyboardCore
+  - IQTextView (1.0.5):
+    - IQKeyboardToolbar/Placeholderable
+  - Kingfisher (6.3.1)
+  - MJRefresh (3.7.9)
+  - Moya (15.0.0):
+    - Moya/Core (= 15.0.0)
+  - Moya/Core (15.0.0):
+    - Alamofire (~> 5.0)
+  - netfox (1.21.0)
+  - Realm (20.0.3):
+    - Realm/Headers (= 20.0.3)
+  - Realm/Headers (20.0.3)
+  - RealmSwift (20.0.3):
+    - Realm (= 20.0.3)
+  - SnapKit (5.7.1)
+  - SVProgressHUD (2.3.1):
+    - SVProgressHUD/Core (= 2.3.1)
+  - SVProgressHUD/Core (2.3.1)
+  - SwiftDate (7.0.0)
+  - swiftScan (1.2.1)
+  - TZImagePickerController (3.8.9):
+    - TZImagePickerController/Basic (= 3.8.9)
+    - TZImagePickerController/Location (= 3.8.9)
+  - TZImagePickerController/Basic (3.8.9)
+  - TZImagePickerController/Location (3.8.9)
+  - TZScrollViewPopGesture (1.0.6)
+  - YYModel (1.0.4)
+  - YYText (1.0.7)
+
+DEPENDENCIES:
+  - FDFullscreenPopGesture
+  - HandyJSON
+  - IQKeyboardManagerSwift
+  - Kingfisher (~> 6.0)
+  - MJRefresh
+  - Moya
+  - netfox
+  - RealmSwift
+  - SnapKit
+  - SVProgressHUD
+  - SwiftDate
+  - swiftScan
+  - TZImagePickerController
+  - TZScrollViewPopGesture
+  - YYModel
+  - YYText
+
+SPEC REPOS:
+  https://gitee.com/mirrors/CocoaPods-Specs.git:
+    - Alamofire
+    - FDFullscreenPopGesture
+    - HandyJSON
+    - IQKeyboardCore
+    - IQKeyboardManagerSwift
+    - IQKeyboardNotification
+    - IQKeyboardReturnManager
+    - IQKeyboardToolbar
+    - IQKeyboardToolbarManager
+    - IQTextInputViewNotification
+    - IQTextView
+    - Kingfisher
+    - MJRefresh
+    - Moya
+    - netfox
+    - Realm
+    - RealmSwift
+    - SnapKit
+    - SVProgressHUD
+    - SwiftDate
+    - swiftScan
+    - TZImagePickerController
+    - TZScrollViewPopGesture
+    - YYModel
+    - YYText
+
+SPEC CHECKSUMS:
+  Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
+  FDFullscreenPopGesture: a8a620179e3d9c40e8e00256dcee1c1a27c6d0f0
+  HandyJSON: 9e4e236f5d2dbefad5155a77417bbea438201c03
+  IQKeyboardCore: 28c8bf3bcd8ba5aa1570b318cbc4da94b861711e
+  IQKeyboardManagerSwift: 835fc9c6e4732398113406d84900ad2e8f141218
+  IQKeyboardNotification: d7382c4466c5a5adef92c7452ebf861b36050088
+  IQKeyboardReturnManager: 972be48528ce9e7508ab3ab15ac7efac803f17f5
+  IQKeyboardToolbar: d4bdccfb78324aec2f3920659c77bb89acd33312
+  IQKeyboardToolbarManager: 6c693c8478d6327a7ef2107528d29698b3514dbb
+  IQTextInputViewNotification: f5e954d8881fd9808b744e49e024cc0d4bcfe572
+  IQTextView: ae13b4922f22e6f027f62c557d9f4f236b19d5c7
+  Kingfisher: 016c8b653a35add51dd34a3aba36b580041acc74
+  MJRefresh: ff9e531227924c84ce459338414550a05d2aea78
+  Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee
+  netfox: 9d5cc727fe7576c4c7688a2504618a156b7d44b7
+  Realm: 853e5089d6042dff807bda000277eadfe2da93d2
+  RealmSwift: f33c19577cefcbf681345d721fcbc7b42be4c949
+  SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a
+  SVProgressHUD: 4837c74bdfe2e51e8821c397825996a8d7de6e22
+  SwiftDate: bbc26e26fc8c0c33fbee8c140c5e8a68293a148a
+  swiftScan: 0849e7d7c1c641384767a573ee8cb90b88d1ddd9
+  TZImagePickerController: 456f470b5dea97b37226ec7a694994a8663340b2
+  TZScrollViewPopGesture: d36355038259e89372a1f4a2db7e9ca675de2278
+  YYModel: 2a7fdd96aaa4b86a824e26d0c517de8928c04b30
+  YYText: 5c461d709e24d55a182d1441c41dc639a18a4849
+
+PODFILE CHECKSUM: 1cbd737c5d19b063216ec530dc4f6434a663b4cd
+
+COCOAPODS: 1.16.2
diff --git a/LingQi/podfile b/LingQi/podfile
new file mode 100644 (file)
index 0000000..6e15b3f
--- /dev/null
@@ -0,0 +1,31 @@
+source "https://gitee.com/mirrors/CocoaPods-Specs.git"
+platform :ios, '13.0'
+use_frameworks!
+
+
+workspace 'LingQi'
+project 'LingQi.xcodeproj'
+target 'LingQi' do
+#  pod 'Toast-Swift'
+  pod 'SnapKit'#布局
+  pod 'YYText'#富文本
+  pod 'FDFullscreenPopGesture'#侧滑返回
+  pod 'TZScrollViewPopGesture'#侧滑返回
+  pod 'IQKeyboardManagerSwift'#键盘
+  pod 'MJRefresh'#刷新
+  pod 'YYModel'#model解析
+  pod 'HandyJSON'#model解析
+  pod 'RealmSwift'#数据库
+  pod 'SwiftDate'#时间转换
+  pod 'SVProgressHUD'#蒙版
+  pod 'Kingfisher', '~> 6.0'#图片下载
+#   pod 'FSPagerView'
+  ##   pod 'Alamofire'
+  pod 'Moya'#网络
+  pod 'swiftScan'#二维码
+  pod 'TZImagePickerController'#图片选择
+  pod 'netfox'#调试
+#  pod 'DoraemonKit'#调试
+end
+
+