Commit 728e2eae authored by 刘俊宏's avatar 刘俊宏

完成自定义富文本编辑器

parent d5f44a55
......@@ -334,6 +334,7 @@
F93E320D2473DA1C00524DFC /* GeliAlertTextFiled.swift in Sources */ = {isa = PBXBuildFile; fileRef = F93E320C2473DA1C00524DFC /* GeliAlertTextFiled.swift */; };
F93E320F2473DF2300524DFC /* GeliAlertTextView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F93E320E2473DF2300524DFC /* GeliAlertTextView.xib */; };
F93E32112473E05C00524DFC /* GeliAlertTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F93E32102473E05C00524DFC /* GeliAlertTextView.swift */; };
F942A7FD247500C300FDFC47 /* TestClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F942A7FC247500C300FDFC47 /* TestClass.swift */; };
F94A314724624E9500FEC38E /* GetGelipayInfoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F94A314624624E9500FEC38E /* GetGelipayInfoModel.swift */; };
F94A314924624FA400FEC38E /* ShopAdministratorInfoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F94A314824624FA400FEC38E /* ShopAdministratorInfoModel.swift */; };
F94A314B246250DB00FEC38E /* GoodsDetailModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F94A314A246250DB00FEC38E /* GoodsDetailModel.swift */; };
......@@ -832,6 +833,7 @@
F93E320C2473DA1C00524DFC /* GeliAlertTextFiled.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeliAlertTextFiled.swift; sourceTree = "<group>"; };
F93E320E2473DF2300524DFC /* GeliAlertTextView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = GeliAlertTextView.xib; sourceTree = "<group>"; };
F93E32102473E05C00524DFC /* GeliAlertTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeliAlertTextView.swift; sourceTree = "<group>"; };
F942A7FC247500C300FDFC47 /* TestClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestClass.swift; sourceTree = "<group>"; };
F94A314624624E9500FEC38E /* GetGelipayInfoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetGelipayInfoModel.swift; sourceTree = "<group>"; };
F94A314824624FA400FEC38E /* ShopAdministratorInfoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShopAdministratorInfoModel.swift; sourceTree = "<group>"; };
F94A314A246250DB00FEC38E /* GoodsDetailModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoodsDetailModel.swift; sourceTree = "<group>"; };
......@@ -2134,6 +2136,7 @@
F956D572246A2D9C003FF510 /* LMNToolBar.m */,
F956D573246A2D9C003FF510 /* LMNWebViewController.m */,
F956D574246A2D9C003FF510 /* LMNImageInputViewController.m */,
F942A7FC247500C300FDFC47 /* TestClass.swift */,
);
path = OtherViews;
sourceTree = "<group>";
......@@ -2886,6 +2889,7 @@
F956D5A1246A2D9C003FF510 /* LMNToolBar.m in Sources */,
F950FDDC24518B9500C40530 /* FSCalendar.m in Sources */,
E0206327246CD84A007A40C4 /* TitleAndLblView.swift in Sources */,
F942A7FD247500C300FDFC47 /* TestClass.swift in Sources */,
F950FDD824518B9500C40530 /* FSCalendarDelegationProxy.m in Sources */,
E01EA1A0245A5D6B00F019D5 /* YunDanXiangQingViewController.swift in Sources */,
F956D5A0246A2D9C003FF510 /* LMNImageView.m in Sources */,
......@@ -3134,6 +3138,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = GeliBusinessPlatform/GeliBusinessPlatform.entitlements;
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = NO;
DEVELOPMENT_ASSET_PATHS = "\"GeliBusinessPlatform/Preview Content\"";
DEVELOPMENT_TEAM = K48346UACH;
ENABLE_PREVIEWS = YES;
......@@ -3153,6 +3158,7 @@
"$(PROJECT_DIR)/GeliBusinessPlatform/Other/JPush/Lib",
);
PRODUCT_BUNDLE_IDENTIFIER = GeliBusinessPlatform.GeliBusinessPlatform;
PRODUCT_MODULE_NAME = TestClass;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = "$(SRCROOT)/GeliBusinessPlatform/Define/Bridge_Header.h";
......@@ -3170,6 +3176,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = GeliBusinessPlatform/GeliBusinessPlatform.entitlements;
CODE_SIGN_STYLE = Automatic;
DEFINES_MODULE = NO;
DEVELOPMENT_ASSET_PATHS = "\"GeliBusinessPlatform/Preview Content\"";
DEVELOPMENT_TEAM = K48346UACH;
ENABLE_PREVIEWS = YES;
......@@ -3189,6 +3196,7 @@
"$(PROJECT_DIR)/GeliBusinessPlatform/Other/JPush/Lib",
);
PRODUCT_BUNDLE_IDENTIFIER = GeliBusinessPlatform.GeliBusinessPlatform;
PRODUCT_MODULE_NAME = TestClass;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
......
......@@ -15,6 +15,17 @@
#import "LMNImageView.h"
#import "LMNImageInputViewController.h"
#import "LMNWebViewController.h"
#import "TestClass-Swift.h"
// 屏幕宽度
#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
// 屏幕高度
#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height
#define NavHeight (KISIphoneX ? 88 : 64)
#define KISIphoneX (CGSizeEqualToSize(CGSizeMake(375.f, 812.f), [UIScreen mainScreen].bounds.size) || CGSizeEqualToSize(CGSizeMake(812.f, 375.f), [UIScreen mainScreen].bounds.size))
#define BOUNSNavHeight CGRectMake(0, NavHeight, SCREEN_WIDTH, SCREEN_HEIGHT - NavHeight)
#define BOUNS self.view.bounds
@interface LMNoteViewController () <UITextViewDelegate, LMNToolBarDelegate, LMNImageInputViewControllerDelegate>
......@@ -47,7 +58,9 @@
LMNTextView *textView = [[LMNTextView alloc] initWithTextStorage:self.draft.textStorage];
textView.backgroundColor = [UIColor whiteColor];
textView.spellCheckingType = UITextSpellCheckingTypeNo;
textView.textColor = [UIColor colorWithRed:68/255.0 green:68/255.0 blue:68/255.0 alpha:1.0];
textView.delegate = self;
textView.imgArr = [NSMutableArray arrayWithCapacity:10];
textView;
});
[self.view addSubview:self.textView];
......@@ -62,6 +75,8 @@
});
[self.view addSubview:self.editButton];
self.toolBar = ({
LMNToolBar *toolBar = [LMNToolBar toolBar];
toolBar.delegate = self;
......@@ -78,17 +93,40 @@
[self loadSubviews];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"HTML" style:UIBarButtonItemStylePlain target:self action:@selector(export)];
}
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"保存" style:UIBarButtonItemStylePlain target:self action:@selector(export)];
[self.navigationItem.rightBarButtonItem setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont boldSystemFontOfSize:14],NSFontAttributeName, nil] forState:UIControlStateNormal];
self.navigationItem.title = @"编辑商品详情";
UIView *containerView = [UIView new];
containerView.frame = (CGRect){.size = CGSizeMake(34, 30)}; // 系统BarButtonItem大小(34, 30)
UIButton *button1 = [UIButton buttonWithType:UIButtonTypeCustom];
button1.frame = (CGRect){.size = CGSizeMake(34, 30)};
[button1 addTarget:self action:@selector(outVC) forControlEvents:UIControlEventTouchUpInside];
[containerView addSubview:button1];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 5, 10, 17);
[button setBackgroundImage:[UIImage imageNamed:@"fanhui"] forState:UIControlStateNormal];
[button addTarget:self action:@selector(outVC) forControlEvents:UIControlEventTouchUpInside];
[containerView addSubview:button];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:containerView];
}
- (void)outVC {
NSLog(@"outvc====outvc");
[self.navigationController popViewControllerAnimated:YES];
}
- (void)layoutTextView
{
CGFloat toolbarHeight = 44.f;
self.textView.frame = self.view.bounds;
self.textView.frame = BOUNS;
self.toolBar.frame = ({
CGRect rect = self.view.bounds;
CGRect rect = BOUNS;
rect.size.height = toolbarHeight;
rect.origin.y = CGRectGetHeight(self.view.bounds) - CGRectGetHeight(rect) - self.keyboardHeight;
rect.origin.y = CGRectGetHeight(BOUNS) - CGRectGetHeight(rect) - self.keyboardHeight;
rect;
});
UIEdgeInsets insets = self.textView.contentInset;
......@@ -97,6 +135,8 @@
insets.bottom += toolbarHeight;
}
self.textView.contentInset = insets;
self.textView.textColor = [UIColor colorWithRed:68/255.0 green:68/255.0 blue:68/255.0 alpha:1.0];
}
- (void)viewDidLayoutSubviews
......@@ -107,14 +147,14 @@
self.editButton.frame = ({
CGRect rect = CGRectZero;
rect.size = CGSizeMake(50.f, 50.f);
rect.origin.x = CGRectGetWidth(self.view.bounds) - 50.f - 20.f;
rect.origin.y = CGRectGetHeight(self.view.bounds) - 50.f - 20.f - self.keyboardHeight;
rect.origin.x = CGRectGetWidth(BOUNS) - 50.f - 20.f;
rect.origin.y = CGRectGetHeight(BOUNS) - 50.f - 20.f - self.keyboardHeight;
rect;
});
self.editButton.layer.cornerRadius = 25.f;
self.toolBar.frame = ({
CGRect rect = self.view.bounds;
CGRect rect = BOUNS;
rect.origin.y = CGRectGetHeight(rect) - 44.f - self.keyboardHeight;
rect.size.height = 44.f;
rect;
......@@ -175,10 +215,7 @@
- (void)export
{
[self.textView exportHTML:^(BOOL succeed, NSString *html) {
NSLog(@"html:\n%@", html);
LMNWebViewController *vc = [[LMNWebViewController alloc] init];
vc.html = html;
[self.navigationController pushViewController:vc animated:YES];
NSLog(@"html:\n%@", [NSString stringWithFormat:@"<html>%@</html>",html]);
}];
}
......@@ -205,9 +242,9 @@
break;
}
if (inputViewController && self.currentInputController != inputViewController) {
CGRect rect = self.view.bounds;
rect.size.height = 260.f;
rect.origin.y = CGRectGetHeight(self.view.bounds) - CGRectGetHeight(rect);
CGRect rect = BOUNS;
rect.size.height = 400.f;
rect.origin.y = CGRectGetHeight(BOUNS) - CGRectGetHeight(rect);
inputViewController.view.frame = rect;
}
self.currentInputController = inputViewController;
......@@ -361,6 +398,7 @@
}
#pragma mark - <LMNImageInputViewControllerDelegate>
#pragma mark -- 插入图片
- (void)lmn_imageInput:(LMNImageInputViewController *)viewController didSelectPHAsset:(PHAsset *)asset
{
......@@ -370,6 +408,7 @@
CGFloat imageWidth = CGRectGetWidth([UIScreen mainScreen].bounds) - 40.f;
CGSize targetSize = CGSizeMake(imageWidth, imageWidth);
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.synchronous = YES;
options.networkAccessAllowed = YES;
__block LMNImageView *imageView = nil;
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:targetSize contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage *result, NSDictionary *info) {
......@@ -380,6 +419,22 @@
else {
imageView.image = result;
}
//请求上传图片
TestClass *model = [[TestClass alloc]init];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:10];
[dict setValue:@"RQdwz5QKpeg=" forKey:@"user_token"];
[model saveFileWithImage:result params:dict success:^(NSDictionary<NSString *,id> * data) {
if ([[NSString stringWithFormat:@"%@",data[@"code"]]isEqualToString:@"1"]) {
NSDictionary *dataDic = data[@"data"];
NSString *url = dataDic[@"url"];
[self.textView.imgArr addObject:url];
imageView.imageUrl = url;
}
} failture:^(NSError * error) {
}];
}];
}
......
......@@ -23,6 +23,7 @@
@interface LMNImageView : UIView
@property (nonatomic, weak) id<LMNImageViewDelegate> delegate;
@property (nonatomic, strong) NSString *imageUrl;
@property (nonatomic, strong) UIImage *image;
@property (nonatomic, strong) UIBezierPath *exclusionPath;
......
......@@ -85,11 +85,11 @@ UIImage *lmn_getRectangleImageWithOptions(CGSize size, BOOL opaque, CGFloat scal
_toolBar.backgroundColor = [UIColor whiteColor];
NSMutableArray *itemButtons = [NSMutableArray array];
NSArray *images = @[
[UIImage imageNamed:@"lmn_tool_a"],
[UIImage imageNamed:@"lmn_tool_t"],
[UIImage imageNamed:@"lmn_list"],
[UIImage imageNamed:@"lmn_list_checkbox"],
[UIImage imageNamed:@"lmn_alignment_left"],
// [UIImage imageNamed:@"lmn_tool_a"],
// [UIImage imageNamed:@"lmn_tool_t"],
// [UIImage imageNamed:@"lmn_list"],
// [UIImage imageNamed:@"lmn_list_checkbox"],
// [UIImage imageNamed:@"lmn_alignment_left"],
[UIImage imageNamed:@"lmn_tool_image"],
[UIImage imageNamed:@"lmn_tool_close"]
];
......@@ -104,26 +104,26 @@ UIImage *lmn_getRectangleImageWithOptions(CGSize size, BOOL opaque, CGFloat scal
forControlEvents:UIControlEventTouchUpInside];
switch (idx) {
// case 0:
// _fontButton = button;
// break;
// case 1:
// _titleButton = button;
// break;
// case 2:
// _listButton = button;
// break;
// case 3:
// _checkboxButton = button;
// break;
// case 4:
// _alignmentButton = button;
// break;
case 0:
_fontButton = button;
break;
case 1:
_titleButton = button;
break;
case 2:
_listButton = button;
break;
case 3:
_checkboxButton = button;
break;
case 4:
_alignmentButton = button;
break;
case 5:
button.tag = LMNToolBarItemTagImage;
_imageButton = button;
break;
case 6:
case 1:
_dismissButton = button;
break;
default:
......
//
// TestClass.swift
// GeliBusinessPlatform
//
// Created by 刘俊宏 on 2020/5/20.
// Copyright © 2020 junye lu. All rights reserved.
//
import UIKit
import Alamofire
import SwiftyJSON
import ObjectMapper
class TestClass: NSObject {
@objc func showHelloWithName(name : String) -> Void {
print("\(name) Hello World")
}
//MARK:--图片(文件)上传
@objc func saveFile(image: UIImage,params:[String:Any],success:@escaping (_ res:Dictionary<String, Any>)->(),failture:@escaping(_ error:Error)->()) {
NetworkRequest.sharedInstance.uploadImage(url: "图片(文件)上传", image: image, params: params, success: { (data) in
success(data)
}) { (error) in
failture(error)
}
}
}
......@@ -19,7 +19,10 @@
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
NSMutableString *html = [NSMutableString string];
LMNLine *line = self.chain.rootLine;
int i = 0;
do {
NSRange range = line.range;
if (line.next) {
range.length -= 1;
......@@ -27,8 +30,11 @@
NSAttributedString *attributedText = [self attributedSubstringFromRange:range];
if ([line isKindOfMode:LMNLineModeModeImage]) {
// TODO: 图片部分逻辑未处理。
NSString *imgSrc = @"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1529656898878&di=530af28e54a9418a36e7b27b018f2df1&imgtype=0&src=http%3A%2F%2Fimg4.duitang.com%2Fuploads%2Fitem%2F201406%2F13%2F20140613210905_SEWfr.jpeg";
[html appendFormat:@"<img src=\"%@\" width=\"100%%\"/>", imgSrc];
NSString *imgSrc = @"https://c.gelifood.com/";
NSString *imgUrl = self.imgArr[i];
i += 1;
[html appendFormat:@"<p><img src=\"%@%@\" style=\"max-width:100%%;\"><br></p>", imgSrc,imgUrl];
}
else {
NSMutableString *lineHTML = [NSMutableString string];
......@@ -75,15 +81,15 @@
[html appendFormat:@"<input class=\"%@\" type=\"checkbox\" %@>%@</p>", styleClass, checked, lineHTML];
}
else {
[html appendFormat:@"<p class=\"%@\">%@</p>", styleClass, lineHTML];
[html appendFormat:@"<p>%@</p>", lineHTML];
}
}
line = line.next;
} while (line);
dispatch_async(dispatch_get_main_queue(), ^{
[html insertString:@"<!DOCTYPE html><html><style type=\"text/css\">.title{font-size: 24px;};.subtitle {font-size: 20px;};.content{font-size: 17px;}</style><body>" atIndex:0];
[html appendString:@"</body></html>"];
// [html insertString:@"<!DOCTYPE html><html><style type=\"text/css\">.title{font-size: 24px;};.subtitle {font-size: 20px;};.content{font-size: 17px;}</style><body>" atIndex:0];
// [html appendString:@"</body></html>"];
completion(YES, [html copy]);
});
});
......
......@@ -13,6 +13,7 @@
@class LMNLineChain;
@interface LMNTextStorage : NSTextStorage
@property (nonatomic, strong) NSMutableArray *imgArr;
@property (nonatomic, strong, readonly) LMNLineChain *chain;
@property (nonatomic, assign, readonly) BOOL inProcessEditing;
......
......@@ -13,6 +13,7 @@
@class LMNImageView;
@interface LMNTextView : UITextView
@property (nonatomic, strong) NSMutableArray *imgArr;
- (instancetype)initWithTextStorage:(LMNTextStorage *)textStorage;
......
......@@ -38,6 +38,7 @@ if (!ignore) { \
@implementation LMNTextView
{
LMNTextStorage *_textStorage;
}
- (instancetype)init
......@@ -384,6 +385,9 @@ static CGFloat const kDefaultTextInset = 5.f; // 默认文字会有5.f的缩
- (void)exportHTML:(void (^)(BOOL succeed, NSString *html))completion
{
_textStorage.imgArr = [NSMutableArray arrayWithCapacity:10];
[_textStorage.imgArr removeAllObjects];
[_textStorage.imgArr addObjectsFromArray:self.imgArr];
[_textStorage exportHTML:completion];
}
......@@ -473,6 +477,8 @@ static CGFloat const kDefaultTextInset = 5.f; // 默认文字会有5.f的缩
[nextline insteadOfLine:line];
[_textStorage updateNumberingStartWithLine:nextline];
});
[self.imgArr removeObject:imageView.imageUrl];
}
@end
......@@ -43,15 +43,15 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate, UITabBarControllerDeleg
//MARK:--loginVC
func addLoginVc (isAgain:Bool){
//
let vc = LoginViewController()
vc.delegate = self
let contentView = vc
// let vc = LoginViewController()
// vc.delegate = self
// let contentView = vc
// let vc = ProductDetailViewController()
// //
// let contentView = vc
let vc = LMNoteViewController()
//
let contentView = vc
if let windowScene = sceneC as? UIWindowScene {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment