Selaa lähdekoodia

#mvc封装成动态库

zxs 1 viikko sitten
vanhempi
commit
e54a982bc5
9 muutettua tiedostoa jossa 5541 lisäystä ja 2743 poistoa
  1. 1 0
      CMakeLists.txt
  2. BIN
      lib/windows/mvc/mvc.dll
  3. BIN
      lib/windows/mvc/mvc.lib
  4. 32 0
      mvc/CMakeLists.txt
  5. 9 0
      mvc/mvc_impl.cpp
  6. 2748 0
      mvc/mvc_impl.h
  7. 2 0
      robot/robotics/json.hpp
  8. 1 2743
      robot/robotics/mvc.hpp
  9. 2748 0
      robot/robotics/mvc_impl.h

+ 1 - 0
CMakeLists.txt

@@ -21,6 +21,7 @@ elseif(UNIX)
     add_definitions(-DLINUX_BUILD)
 endif()
 # 包含子项目。
+add_subdirectory ("mvc")
 add_subdirectory ("robot")
 add_subdirectory ("logger")
 add_subdirectory ("drivers")

BIN
lib/windows/mvc/mvc.dll


BIN
lib/windows/mvc/mvc.lib


+ 32 - 0
mvc/CMakeLists.txt

@@ -0,0 +1,32 @@
+# CMakeList.txt: robot 的 CMake 项目,在此处包括源代码并定义
+# 项目特定的逻辑。
+#
+if (WIN32)
+    link_directories("${CMAKE_CURRENT_SOURCE_DIR}/../lib/windows/rttr" "${CMAKE_CURRENT_SOURCE_DIR}/../lib/windows/boost" "${CMAKE_CURRENT_SOURCE_DIR}/../lib/windows/openssl")
+elseif(IOS)
+elseif(UNIX)
+    link_directories("${CMAKE_CURRENT_SOURCE_DIR}/../lib/linux/rttr" "${CMAKE_CURRENT_SOURCE_DIR}/../lib/linux/boost")
+endif()
+# 将源代码添加到此项目的可执行文件。
+add_library(mvc SHARED "mvc_impl.h" "mvc_impl.cpp")
+
+if (CMAKE_VERSION VERSION_GREATER 3.12)
+  set_property(TARGET mvc PROPERTY CXX_STANDARD 20)
+endif()
+
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../include)
+
+# 添加 /bigobj 选项
+if (MSVC)
+    target_compile_options(mvc PRIVATE /bigobj)
+endif()
+
+if (WIN32)
+    target_link_libraries(mvc rttr_core libcrypto libssl Crypt32)
+    add_definitions(-DMVC_EXPORTS)
+elseif(IOS)
+elseif(UNIX)
+    target_link_libraries(mvc pthread rttr_core cppdb crypto ssl dl X11)
+endif()
+# TODO: 如有需要,请添加测试并安装目标。

+ 9 - 0
mvc/mvc_impl.cpp

@@ -0,0 +1,9 @@
+#include "mvc_impl.h"
+
+namespace robotics::v3::mvc {
+	mvc_route												 ico_controller::controllers_;
+	std::mutex												 http_context::mutex_;
+	std::map<std::thread::id, std::shared_ptr<http_context>> http_context::http_context_list_;
+	std::vector<std::shared_ptr<session>>					 sessions::sessions_;
+	std::mutex												 sessions::mutex_;
+}

+ 2748 - 0
mvc/mvc_impl.h

@@ -0,0 +1,2748 @@
+#pragma once
+#ifdef WINDOWS_BUILD
+#ifdef MVC_EXPORTS
+#define MVC_API _declspec(dllexport)
+#else
+#define MVC_API _declspec(dllimport)
+#endif
+#elif LINUX_BUILD
+#define MVC_API
+#endif
+//asio2
+#include <asio2/asio2.hpp>
+//robotics
+#include "../robot/robotics/utils.hpp"
+#include "../robot/robotics/json.hpp"
+#include "../robot/robotics/CImg.h"
+
+namespace robotics {
+	namespace v3 {
+		namespace mvc {
+			class web_reflect {
+			public:
+				/**
+				 * @brief
+				 * @param obj
+				 */
+				static std::map<std::string, std::string> get_object_value(rttr::instance obj) {
+					std::map<std::string, std::string> result;
+					auto propertys = obj.get_type().get_properties();
+					for (auto& property : propertys) {
+						std::string propName(property.get_name());
+						rttr::variant propValue = property.get_value(obj);
+						rttr::type propType = property.get_type();
+						if (propType == rttr::type::get<int>()) {
+							result[propName] = std::to_string(propValue.get_value<int>());
+						}
+						else if (propType == rttr::type::get<std::int64_t>()) {
+							result[propName] = std::to_string(propValue.get_value<std::int64_t>());
+						}
+						else if (propType == rttr::type::get<float>()) {
+							result[propName] = v3::utils::format("{:.2f}", propValue.get_value<float>());
+						}
+						else if (propType == rttr::type::get<double>()) {
+							result[propName] = v3::utils::format("{:.2f}", propValue.get_value<double>());
+						}
+						else if (propType == rttr::type::get<long>()) {
+							result[propName] = std::to_string(propValue.get_value<long>());
+						}
+						else if (propType == rttr::type::get<bool>()) {
+							result[propName] = propValue.get_value<bool>() ? "true" : "false";
+						}
+						else if (propType == rttr::type::get<std::string>()) {
+							result[propName] = propValue.get_value<std::string>();
+						}
+						else if (propType == rttr::type::get<v3::datetime>()) {
+							result[propName] = propValue.get_value<v3::datetime>().to_string();
+						}
+						else if (propType == rttr::type::get<std::vector<int>>()) {
+							auto vecValue = propValue.get_value<std::vector<int>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+						else if (propType == rttr::type::get<std::vector<std::int64_t>>()) {
+							auto vecValue = propValue.get_value<std::vector<std::int64_t>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+						else if (propType == rttr::type::get<std::vector<float>>()) {
+							auto vecValue = propValue.get_value<std::vector<float>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+						else if (propType == rttr::type::get<std::vector<double>>()) {
+							auto vecValue = propValue.get_value<std::vector<double>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+						else if (propType == rttr::type::get<std::vector<long>>()) {
+							auto vecValue = propValue.get_value<std::vector<long>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+						else if (propType == rttr::type::get<std::vector<bool>>()) {
+							auto vecValue = propValue.get_value<std::vector<bool>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+						else if (propType == rttr::type::get<std::vector<std::string>>()) {
+							auto vecValue = propValue.get_value<std::vector<std::string>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+						else if (propType == rttr::type::get<std::vector<v3::datetime>>()) {
+							auto vecValue = propValue.get_value<std::vector<v3::datetime>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+					}
+					return result;
+				}
+				/**
+				 * @brief
+				 * @param obj
+				 * @param values
+				 */
+				static void set_object_value(rttr::instance obj, std::map<std::string, std::string>const& values) {
+					rttr::instance obj1 = obj.get_type().get_raw_type().is_wrapper() ? obj.get_wrapped_instance() : obj;
+					const auto propertys = obj1.get_derived_type().get_properties();
+					for (auto& property : propertys) {
+						auto name = std::string(property.get_name());
+						auto type = property.get_type();
+						if (!values.contains(name))
+							continue;
+						std::string value = values.find(name)->second;
+						if (type == rttr::type::get<int>()) {
+							property.set_value(obj1, atoi(value.c_str()));
+						}
+						else if (type == rttr::type::get<std::int64_t>()) {
+							property.set_value(obj, std::int64_t(std::atoll(value.c_str())));
+						}
+						else if (type == rttr::type::get<float>()) {
+							property.set_value(obj, float(std::atof(value.c_str())));
+						}
+						else if (type == rttr::type::get<double>()) {
+							property.set_value(obj, double(std::atof(value.c_str())));
+						}
+						else if (type == rttr::type::get<long>()) {
+							property.set_value(obj, long(std::atol(value.c_str())));
+						}
+						else if (type == rttr::type::get<bool>()) {
+							if (value == "1" || value == "true" || value == "TRUE" || value == "True") {
+								property.set_value(obj, true);
+							}
+							else {
+								property.set_value(obj, false);
+							}
+						}
+						else if (type == rttr::type::get<std::string>()) {
+							property.set_value(obj, value);
+						}
+						else if (type == rttr::type::get<v3::datetime>()) {
+							property.set_value(obj, v3::datetime(value));
+						}
+						else if (type == rttr::type::get<std::vector<int>>()) {
+							std::vector<std::string> vec = v3::utils::split(value, ",");
+							std::vector<int> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atoi(vecIt.c_str()));
+							}
+							property.set_value(obj, vecValue);
+						}
+						else if (type == rttr::type::get<std::vector<std::int64_t>>()) {
+							std::vector<std::string> vec = v3::utils::split(value, ",");
+							std::vector<std::int64_t> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atoll(vecIt.c_str()));
+							}
+							property.set_value(obj, vecValue);
+						}
+						else if (type == rttr::type::get<std::vector<float>>()) {
+							std::vector<std::string> vec = v3::utils::split(value, ",");
+							std::vector<float> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atof(vecIt.c_str()));
+							}
+							property.set_value(obj, vecValue);
+						}
+						else if (type == rttr::type::get<std::vector<double>>()) {
+							std::vector<std::string> vec = v3::utils::split(value, ",");
+							std::vector<double> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atof(vecIt.c_str()));
+							}
+							property.set_value(obj, vecValue);
+						}
+						else if (type == rttr::type::get<std::vector<long>>()) {
+							std::vector<std::string> vec = v3::utils::split(value, ",");
+							std::vector<long> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atol(vecIt.c_str()));
+							}
+							property.set_value(obj, vecValue);
+						}
+						else if (type == rttr::type::get<std::vector<bool>>()) {
+							std::vector<std::string> vec = v3::utils::split(value, ",");
+							std::vector<bool> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(vecIt == "1" || vecIt == "true" || vecIt == "TRUE" || vecIt == "True");
+							}
+							property.set_value(obj, vecValue);
+						}
+						else if (type == rttr::type::get<std::vector<std::string>>()) {
+							std::vector<std::string> vecValue = v3::utils::split(value, ",");
+							property.set_value(obj, vecValue);
+						}
+						else if (type == rttr::type::get<std::vector<v3::datetime>>()) {
+							std::vector<std::string> vec = v3::utils::split(value, ",");
+							std::vector<v3::datetime> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(v3::datetime(vecIt));
+							}
+							property.set_value(obj, vecValue);
+						}
+					}
+				}
+			};
+
+			class cookie_id {
+			public:
+				static std::string get_id() {
+					static std::string g_cookie_id;
+					if (g_cookie_id.empty()) {
+						g_cookie_id = v3::utils::uuid();
+					}
+					return g_cookie_id;
+				}
+			};
+
+			class cookie {
+			public:
+				cookie() {
+					//name = "SessionId";
+					name = cookie_id::get_id();
+					value = v3::utils::base64_encode(v3::utils::uuid());
+					path = "path=/";
+					time = 30 * 60 * 1000;
+					last_expire_time = v3::datetime::current_time_stamp() + time;
+				}
+				/**
+				 * @brief cookie名称
+				 */
+				std::string name;
+				/**
+				 * @brief cookie值
+				 */
+				std::string value;
+				/**
+				 * @brief cookie路径
+				 */
+				std::string path;
+				/**
+				 * @brief cookie时间
+				 */
+				time_t		time = 0;
+				/**
+				 * @brief 上次刷新时间
+				 */
+				time_t last_expire_time = 0;
+				/**
+				 * @brief 对比
+				 * @param cookie
+				 * @param remove
+				 * @return
+				 */
+				bool compare(std::shared_ptr<cookie> cookie, bool& remove) {
+					bool result = false;
+					remove = false;
+					if (cookie) {
+						result = (name == cookie->name && value == cookie->value);
+						if (result) {
+							time_t current_time = v3::datetime::current_time_stamp();
+							if (last_expire_time < current_time) {
+								remove = true;
+								result = false;
+							}
+							else {
+								last_expire_time = v3::datetime::current_time_stamp() + time;
+							}
+						}
+					}
+					return result;
+				}
+			};
+
+			class cookies {
+			public:
+				/**
+				 * @brief 解析
+				 * @param cookie_str
+				 * @return
+				 */
+				static std::shared_ptr<cookies> analysis(std::string const& cookie_str) {
+					std::shared_ptr<cookies> result;
+					std::vector<std::string> cookies_tmp = v3::utils::split(cookie_str, ";");
+					for (auto& item : cookies_tmp) {
+						int index = item.find('=');
+						if (index == std::string::npos)
+							continue;
+						std::shared_ptr<cookie> add(new cookie);
+						add->name = item.substr(0, index);
+						add->value = item.substr(index + 1);
+						add->name = v3::utils::trim(add->name);
+						add->value = v3::utils::trim(add->value);
+						if (add->name != "path") {
+							if (!result) {
+								result.reset(new cookies);
+							}
+							result->cookies_.push_back(add);
+						}
+					}
+					return result;
+				}
+				/**
+				 * @brief 对比
+				 * @param value
+				 * @return
+				 */
+				bool compare(std::shared_ptr<cookies> value) {
+					bool result = false;
+					if (!value)
+						return result;
+					for (auto& value_elem : value->cookies_) {
+						for (int i = 0; i < cookies_.size(); ++i) {
+							bool is_remove = false;
+							bool exist = cookies_[i]->compare(value_elem, is_remove);
+							if (is_remove) {
+								cookies_.erase(cookies_.begin() + i);
+								--i;
+								continue;
+							}
+							if (exist) {
+								result = true;
+							}
+						}
+					}
+					return result;
+				}
+				/**
+				 * @brief 数量
+				 * @return
+				 */
+				int count() {
+					return int(cookies_.size());
+				}
+				/**
+				 * @brief 添加
+				 * @param cookie
+				 */
+				void add(std::shared_ptr<cookie> cookie) {
+					cookies_.push_back(cookie);
+				}
+			private:
+				std::vector<std::shared_ptr<cookie>>	cookies_;
+			};
+
+			struct session {
+				/**
+				 * @brief 关闭
+				 */
+				bool							close = false;
+				/**
+				 * @brief
+				 */
+				bool							authen = false;
+				/**
+				 * @brief
+				 */
+				std::shared_ptr<cookies>		cookies_;
+				/**
+				 * @brief
+				 */
+				std::map<std::string, std::any>	user_data;
+			};
+
+			class MVC_API sessions {
+			public:
+				/**
+				 * @brief
+				 */
+				static void add_session(std::shared_ptr<session> session) {
+					std::lock_guard<std::mutex> locker(mutex_);
+					sessions_.push_back(session);
+				}
+				/**
+				 * @brief
+				 */
+				static std::shared_ptr<session> get_session(std::string const& cookie_str) {
+					std::shared_ptr<session> result;
+					std::shared_ptr<cookies> cookies = cookies::analysis(cookie_str);
+					{
+						std::lock_guard<std::mutex> locker(mutex_);
+						for (int i = 0; i < sessions_.size(); ++i) {
+							if (sessions_[i]->cookies_->compare(cookies) && !sessions_[i]->close) {
+								result = sessions_[i];
+							}
+							else if (sessions_[i]->cookies_->count() <= 0 || sessions_[i]->close) {
+								sessions_.erase(sessions_.begin() + i);
+								i--;
+							}
+						}
+					}
+					return result;
+				}
+			private:
+				static std::vector<std::shared_ptr<session>> sessions_;
+				static std::mutex							 mutex_;
+			};
+
+			enum class captcha_type {
+				/**
+				 * @brief 成功
+				 */
+				success,
+				/**
+				 * @brief 失败
+				 */
+				fail,
+				/**
+				 * @brief 没有验证码
+				 */
+				no
+			};
+
+			struct controller_action;
+
+			class MVC_API http_context {
+			public:
+				class curr {
+				public:
+					/**
+					 * @brief 当前context
+					 * @return
+					 */
+					static std::shared_ptr<http_context> current() {
+						return http_context::current();
+					}
+					/**
+					 * @brief 是否有权限
+					 * @return
+					 */
+					static bool authen() {
+						return current()->authen();
+					}
+					/**
+					 * @brief 设置权限
+					 * @param value
+					 */
+					static void set_authen(bool value = true) {
+						current()->set_authen(value);
+					}
+					/**
+					 * @brief 设置session
+					 * @param key
+					 * @param value
+					 */
+					static void add_session(std::string const& key, std::any const& value) {
+						current()->add_session(key, value);
+					}
+					/**
+					 * @brief 添加session并设置权限
+					 * @param key
+					 * @param value
+					 */
+					static void add_authen_session(std::string const& key, std::any const& value) {
+						add_session(key, value);
+						set_authen();
+					}
+					/**
+					 * @brief 获取session
+					 * @param key
+					 * @return
+					 */
+					static std::any& session(std::string const& key) {
+						return current()->session(key);
+					}
+					/**
+					 * @brief 获取session
+					 * @tparam _Ret
+					 * @param key
+					 * @param succ
+					 * @return
+					 */
+					template<typename _Ret>
+					static bool get_session(std::string const& key, _Ret& result) {
+						std::any any_value = current()->session(key);
+						if (any_value.type() != typeid(_Ret)) {
+							return false;
+						}
+						result = std::any_cast<_Ret>(any_value);
+						return true;
+					}
+					/**
+					 * @brief 添加cookie
+					 * @param timeout
+					 */
+					static void add_cookie(int timeout = 30) {
+						current()->add_cookie(timeout);
+					}
+					/**
+					 * @brief 删除cookie
+					 */
+					static void remove_cookie() {
+						current()->remove_cookie();
+					}
+					/**
+					 * @brief 重置cookie
+					 * @param timeout
+					 */
+					static void reset_cookie(int timeout = 30) {
+						remove_cookie();
+						add_cookie(timeout);
+					}
+					/**
+					 * @brief 验证码比较
+					 * @param key
+					 * @param captcha_code
+					 * @return
+					 */
+					static captcha_type captcha_compare(std::string const& key, std::string const& captcha_code) {
+						std::string value;
+						if (!get_session<std::string>(key, value))
+							return mvc::captcha_type::no;
+						else if (v3::utils::case_insensitive_compare(value, captcha_code))
+							return mvc::captcha_type::success;
+						else
+							return mvc::captcha_type::fail;
+					}
+					/**
+					 * @brief 验证码比较
+					 * @param key
+					 * @param captcha_code
+					 * @param success
+					 * @param message
+					 * @return
+					 */
+					static bool captcha_compare(std::string const& key, std::string const& captcha_code, bool& success, std::string& message) {
+						auto result = captcha_compare(key, captcha_code);
+						if (mvc::captcha_type::no == result) {
+							success = false;
+							message = "验证码不存在!";
+							return false;
+						}
+						else if (mvc::captcha_type::fail == result) {
+							success = false;
+							message = "验证码错误!";
+							return false;
+						}
+						else {
+							success = true;
+							message = "成功!";
+							return true;
+						}
+					}
+				};
+				/**
+				 * @brief
+				 */
+				static void new_curr_http_context(http::web_request& req, http::web_response& rep) {
+					rep.clear();
+					new http_context(req, rep);
+				}
+				/**
+				 * @brief
+				 */
+				static void remove_curr_http_context() {
+					std::lock_guard<std::mutex> locker(mutex_);
+					http_context_list_.erase(std::this_thread::get_id());
+				}
+				/**
+				 * @brief
+				 * @param route
+				 * @return
+				 */
+				static std::shared_ptr<http_context> current() {
+					std::lock_guard<std::mutex> locker(mutex_);
+					return http_context_list_[std::this_thread::get_id()];
+				}
+				/**
+				 * @brief
+				 */
+				bool authen() {
+					if (current_session_)
+						return current_session_->authen;
+					return false;
+				}
+				/**
+				 * @brief
+				 */
+				void set_authen(bool value = true) {
+					if (current_session_)
+						current_session_->authen = value;
+				}
+				/**
+				 * @brief
+				 */
+				void add_session(std::string const& key, std::any const& value) {
+					if (!current_session_)
+						throw std::runtime_error("not cookie!");
+					current_session_->user_data[key] = value;
+				}
+				/**
+				 * @brief
+				 */
+				std::any& session(std::string const& key) {
+					static std::any g_any;
+					if (current_session_) {
+						if (current_session_->user_data.find(key) != current_session_->user_data.end()) {
+							return current_session_->user_data[key];
+						}
+					}
+					g_any = std::any();
+					return g_any;
+				}
+				/**
+				 * @brief
+				 */
+				void add_cookie(int timeout = 30) {
+					std::shared_ptr<cookie> item(new cookie);
+					item->time = timeout * (1000 * 60);
+					item->last_expire_time = v3::datetime::current_time_stamp() + item->time;
+					if (current_session_ && !current_session_->close) {
+						if (!current_session_->cookies_)
+							current_session_->cookies_.reset(new cookies);
+						current_session_->cookies_->add(item);
+					}
+					else {
+						current_session_.reset(new mvc::session);
+						current_session_->cookies_.reset(new cookies);
+						current_session_->cookies_->add(item);
+						mvc::sessions::add_session(current_session_);
+					}
+					std::string set_cookie_str;
+					set_cookie_str += item->name;
+					set_cookie_str += "=";
+					set_cookie_str += item->value;
+					set_cookie_str += ";";
+					set_cookie_str += item->path;
+					response.set(http::field::set_cookie, set_cookie_str);
+				}
+				/**
+				 * @brief
+				 */
+				void remove_cookie() {
+					if (current_session_) {
+						current_session_->close = true;
+					}
+					response.set(http::field::set_cookie, "SessionId=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT");
+				}
+				/**
+				 * @brief
+				 */
+				void set_controller_action(std::shared_ptr<controller_action> value) {
+					controller_action_ = value;
+				}
+				/**
+				 * @brief
+				 */
+				std::shared_ptr<controller_action> get_controller_action() {
+					return controller_action_;
+				}
+				/**
+				 * @brief
+				 */
+				http::web_request& request;
+				/**
+				 * @brief
+				 */
+				http::web_response& response;
+				/**
+				 * @brief
+				 */
+				std::filesystem::path root_directory;
+			private:
+				http_context(http::web_request& req, http::web_response& rep) :
+					request(req),
+					response(rep),
+					root_directory(rep.get_root_directory()) {
+					if (req.find(http::field::cookie) != req.end()) {
+						current_session_ = sessions::get_session(std::string(req.find(http::field::cookie)->value().begin(), req.find(http::field::cookie)->value().end()));
+					}
+					std::lock_guard<std::mutex> locker(mutex_);
+					http_context_list_[std::this_thread::get_id()].reset(this);
+				}
+			private:
+				std::shared_ptr<mvc::session> current_session_;
+				std::shared_ptr<controller_action> controller_action_;
+			private:
+				static std::mutex												mutex_;
+				static std::map<std::thread::id, std::shared_ptr<http_context>> http_context_list_;
+			};
+
+			class http_context_gc {
+			public:
+				http_context_gc(http::web_request& req, http::web_response& rep) {
+					http_context::new_curr_http_context(req, rep);
+				}
+				virtual ~http_context_gc() {
+					http_context::remove_curr_http_context();
+				}
+			};
+
+			enum class pseudo_type {
+				NON = 0,
+				MASK,
+				MODEL,
+				FOR,
+				IF,
+				SWITCH,
+				FILE
+			};
+
+			struct class_value {
+				bool is_list = false;
+				std::string class_name;
+				std::vector<std::map<std::string, std::string>> class_value;
+			};
+
+			struct ipseudo_label {
+				ipseudo_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
+					type(value_type.first),
+					label(value_type.second) {
+				}
+				/**
+				 * @brief 类型
+				 */
+				pseudo_type										type;
+				/**
+				 * @brief 原始代码
+				 */
+				std::string										html_code;
+				/**
+				 * @brief 临时原始代码
+				 */
+				std::string										html_code_tmp;
+				/**
+				 * @brief 类名
+				 */
+				std::string										class_name;
+				/**
+				 * @brief 标签
+				 */
+				std::pair<std::string, std::string>				label;
+				/**
+				 * @brief 实体类数据列表
+				 */
+				std::vector<std::map<std::string, std::string>> class_value_list;
+				/**
+				 * @brief 子标签
+				 */
+				std::vector<std::shared_ptr<ipseudo_label>>		childs;
+				/**
+				 * @brief 解析返回html
+				 */
+				virtual std::string analysis() = 0;
+				/**
+				 * @brief 设置属性值
+				 */
+				void set_class_value(std::vector<std::shared_ptr<class_value>>const& value) {
+					for (auto it : childs) {
+						it->set_class_value(value);
+					}
+					for (auto it : value) {
+						if (class_name != it->class_name)
+							continue;
+						if (it->is_list && type == pseudo_type::FOR) {
+							class_value_list = it->class_value;
+							break;
+						}
+						else if (!it->is_list) {
+							class_value_list = it->class_value;
+							break;
+						}
+					}
+				}
+				/**
+				 * @brief 解析基础信息
+				 */
+				virtual void analysis_baseinfo() = 0;
+			protected:
+				std::string extract(std::string const& value, std::pair<std::string, std::string> const& pair, int& index) {
+					std::string result;
+					bool ok = false;
+					int count = 0;
+					for (size_t i = 0; i < value.size(); ++i) {
+						if (i + 1 >= pair.first.size() &&
+							value[i] == pair.first[pair.first.size() - 1] &&
+							value.substr(i - pair.first.size() + 1, pair.first.size()) == pair.first) {
+							count++;
+							if (count == 1) {
+								ok = true;
+								continue;
+							}
+						}
+						if (ok &&
+							value.size() >= i + pair.second.size() &&
+							value[i] == pair.second[0] &&
+							value.substr(i, pair.second.size()) == pair.second) {
+							count--;
+							if (count == 0) {
+								index = i + 1;
+								return result;
+							}
+						}
+						if (ok) {
+							result += value[i];
+						}
+					}
+					index = -1;
+					return result;
+				}
+				std::vector<std::string> extractList(std::string const& value, std::pair<std::string, std::string> const& pair) {
+					std::vector<std::string> result;
+					int index = 0;
+					int pos = 0;
+					while (index > -1) {
+						pos += index;
+						std::string ret = extract(value.substr(pos, value.size() - pos), pair, index);
+						if (index != -1)
+							result.push_back(ret);
+					}
+					return result;
+				}
+			};
+
+			struct pseudo_mask_label : public ipseudo_label {
+				pseudo_mask_label(std::pair<pseudo_type, std::pair<std::string, std::string>>const& value_type) :
+					ipseudo_label(value_type) {
+				}
+				std::string mask_name;
+				virtual std::string analysis()override {
+					for (auto child : childs) {
+						std::string childValue = child->analysis();
+						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
+					}
+					int index = 0;
+					std::string header = extract(html_code_tmp, { "${mask","}" }, index);
+					header = "${mask" + header + "}";
+					std::string tmp = extract(html_code_tmp, { header,"{/mask}" }, index);
+					return tmp;
+				}
+				virtual void analysis_baseinfo() override {
+					html_code_tmp = html_code;
+					for (auto child : childs) {
+						child->analysis_baseinfo();
+					}
+					//获取mask名称
+					int index = 0;
+					mask_name = extract(html_code, { "name='","'" }, index);
+				}
+			};
+
+			struct pseudo_model_label : public ipseudo_label {
+				pseudo_model_label(std::pair<pseudo_type, std::pair<std::string, std::string>>const& value_type) :
+					ipseudo_label(value_type) {
+				}
+				virtual std::string analysis()override {
+					for (auto child : childs) {
+						std::string childValue = child->analysis();
+						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
+					}
+					std::string propName;
+					std::string propValue;
+					std::map<std::string, std::string> mapPropValue;
+					{
+						int index = 0;
+						std::string tmp = extract(html_code_tmp, { "name='","'" }, index);
+						std::string::size_type pos = tmp.find('.');
+						if (pos != std::string::npos) {
+							propName = tmp.substr(pos + 1, tmp.size() - pos - 1);
+						}
+					}
+					//获取值
+					{
+						int index = 0;
+						std::string tmp = extract(html_code_tmp.substr(index, html_code_tmp.size() - index), { "value='[","]'" }, index);
+						//属性值
+						if (tmp == "#value") {
+							propValue = tmp;
+						}
+						else {
+							auto values = v3::utils::split(tmp, ",");
+							for (auto value : values) {
+								auto valueItem = v3::utils::split(value, ":");
+								if (valueItem.size() == 2) {
+									if (valueItem[0].size() >= 2 && valueItem[1].size() >= 2 &&
+										valueItem[0][0] == '\'' && valueItem[0][valueItem[0].size() - 1] == '\'' &&
+										valueItem[1][0] == '\'' && valueItem[1][valueItem[1].size() - 1] == '\'') {
+										valueItem[0].erase(valueItem[0].begin());
+										valueItem[0].erase(valueItem[0].begin() + valueItem[0].size() - 1);
+										valueItem[1].erase(valueItem[1].begin());
+										valueItem[1].erase(valueItem[1].begin() + valueItem[1].size() - 1);
+										mapPropValue[valueItem[0]] = valueItem[1];
+									}
+								}
+							}
+						}
+					}
+					if (propName.empty()) {
+						return "";
+					}
+					//属性值
+					if (!propValue.empty() && !class_value_list.empty()) {
+						if (class_value_list[0].find(propName) != class_value_list[0].end()) {
+							return class_value_list[0][propName];
+						}
+					}
+					else if (!mapPropValue.empty() && !class_value_list.empty()) {
+						if (class_value_list[0].find(propName) != class_value_list[0].end()) {
+							std::string value = class_value_list[0][propName];
+							//选择值
+							if (mapPropValue.find(value) != mapPropValue.end()) {
+								return mapPropValue[value];
+							}
+							//默认值
+							else if (mapPropValue.find("default") != mapPropValue.end()) {
+								if (mapPropValue["default"] == "#value") {
+									return class_value_list[0][propName];
+								}
+								else {
+									return mapPropValue["default"];
+								}
+							}
+						}
+					}
+					return "";
+				}
+				virtual void analysis_baseinfo() override {
+					html_code_tmp = html_code;
+					for (auto child : childs) {
+						child->analysis_baseinfo();
+					}
+					//获取类名属性名
+					int index = 0;
+					std::string tmp = extract(html_code, { "name='","'" }, index);
+					std::string::size_type pos = tmp.find('.');
+					if (pos != std::string::npos) {
+						class_name = tmp.substr(0, pos);
+					}
+				}
+			};
+
+			struct pseudo_for_label : public ipseudo_label {
+				pseudo_for_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
+					ipseudo_label(value_type) {
+				}
+				virtual std::string analysis()override {
+					for (auto child : childs) {
+						std::string childValue = child->analysis();
+						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
+					}
+					std::string resultValue;
+					std::string itemName;
+					std::string forLabel;
+					std::vector<std::string> forItemLabelList;
+					std::map<std::string, std::map<std::string, std::map<std::string, std::string>>> forItemLabelValueList;
+					//获取ITEM名称
+					{
+						int index = 0;
+						itemName = extract(html_code_tmp, { "item='","'" }, index);
+						if (itemName.empty())
+							return "";
+					}
+
+					//提取for标签值
+					{
+						int index = 0;
+						std::string header = extract(html_code_tmp, { "${for","}" }, index);
+						header = "${for" + header + "}";
+						forLabel = extract(html_code_tmp, { header,"{/for}" }, index);
+					}
+
+					//提取foritem标签
+					{
+						forItemLabelList = extractList(forLabel, { "{item","/}" });
+						for (auto& it : forItemLabelList) {
+							it = "{item" + it + "/}";
+						}
+						if (forItemLabelList.empty())
+							return forLabel;
+					}
+
+					//提取foritem参数
+					{
+						int index = 0;
+						std::string header = "name='" + itemName + ".";
+						for (auto it : forItemLabelList) {
+							std::string propName = extract(it, { header,"'" }, index);
+							if (propName.empty())
+								continue;
+							std::string value = extract(it, { "value='[","]'" }, index);
+							if (value.empty())
+								continue;
+							if (value == "#value") {
+								forItemLabelValueList[it][propName][value] = value;
+							}
+							else {
+								auto values = v3::utils::split(value, ",");
+								for (auto valueIt : values) {
+									auto valueItem = v3::utils::split(valueIt, "':'");
+									if (valueItem.size() == 2) {
+										valueItem[0] += "'";
+										valueItem[1] = "'" + valueItem[1];
+										if (valueItem[0].size() >= 2 && valueItem[1].size() >= 2 &&
+											valueItem[0][0] == '\'' && valueItem[0][valueItem[0].size() - 1] == '\'' &&
+											valueItem[1][0] == '\'' && valueItem[1][valueItem[1].size() - 1] == '\'') {
+
+											valueItem[0].erase(valueItem[0].begin());
+											valueItem[0].erase(valueItem[0].begin() + valueItem[0].size() - 1);
+
+											valueItem[1].erase(valueItem[1].begin());
+											valueItem[1].erase(valueItem[1].begin() + valueItem[1].size() - 1);
+
+											forItemLabelValueList[it][propName][valueItem[0]] = valueItem[1];
+										}
+									}
+								}
+							}
+						}
+					}
+
+					//遍历值
+					{
+						int index = 0;
+						for (auto item : class_value_list) {
+							index++;
+							std::string itemValue = forLabel;
+							for (auto forItem : forItemLabelList) {
+								//没有查找到值赋值为空
+								if (forItemLabelValueList.find(forItem) == forItemLabelValueList.end()) {
+									itemValue = v3::utils::replace(itemValue, forItem, "");
+									continue;
+								}
+								//查找属性
+								if (forItemLabelValueList[forItem].find("for-index") != forItemLabelValueList[forItem].end()) {
+
+									//默认值
+									if (forItemLabelValueList[forItem]["for-index"].find("#value") != forItemLabelValueList[forItem]["for-index"].end()) {
+
+										itemValue = v3::utils::replace(itemValue, forItem, std::to_string(index));
+									}
+									else {
+										if (forItemLabelValueList[forItem]["for-index"].find(std::to_string(index)) != forItemLabelValueList[forItem]["for-index"].end()) {
+
+											itemValue = v3::utils::replace(itemValue, forItem, forItemLabelValueList[forItem]["for-index"][std::to_string(index)]);
+										}
+										else if (forItemLabelValueList[forItem]["for-index"].find("default") != forItemLabelValueList[forItem]["for-index"].end()) {
+											itemValue = v3::utils::replace(itemValue, forItem, forItemLabelValueList[forItem]["for-index"]["default"]);
+										}
+										else {
+											itemValue = v3::utils::replace(itemValue, forItem, "");
+										}
+									}
+									continue;
+								}
+								else {
+									std::string propNameItem;
+									std::map<std::string, std::string> propValueItem;
+									auto childItem = forItemLabelValueList[forItem];
+									for (auto childItemIt : childItem) {
+										propNameItem = childItemIt.first;
+										propValueItem = childItemIt.second;
+									}
+									if (propNameItem.empty()) {
+										itemValue = v3::utils::replace(itemValue, forItem, "");
+										continue;
+									}
+									if (item.find(propNameItem) != item.end()) {
+										if (item.find(propNameItem) != item.end()) {
+											if (propValueItem.find("#value") != propValueItem.end()) {
+												itemValue = v3::utils::replace(itemValue, forItem, item[propNameItem]);
+											}
+											else if (propValueItem.find(item[propNameItem]) != propValueItem.end()) {
+												itemValue = v3::utils::replace(itemValue, forItem, propValueItem[item[propNameItem]]);
+											}
+											else if (propValueItem.find("default") != propValueItem.end()) {
+
+												if (propValueItem["default"] == "#value") {
+													itemValue = v3::utils::replace(itemValue, forItem, item[propNameItem]);
+												}
+												else {
+													itemValue = v3::utils::replace(itemValue, forItem, propValueItem["default"]);
+												}
+											}
+											else {
+												itemValue = v3::utils::replace(itemValue, forItem, "");
+											}
+										}
+										else {
+											itemValue = v3::utils::replace(itemValue, forItem, "");
+										}
+									}
+									else {
+										itemValue = v3::utils::replace(itemValue, forItem, "");
+									}
+								}
+							}
+							resultValue += itemValue;
+						}
+					}
+					return resultValue;
+				}
+				virtual void analysis_baseinfo() override {
+					html_code_tmp = html_code;
+					for (auto child : childs) {
+						child->analysis_baseinfo();
+					}
+					//获取类名属性名
+					int index = 0;
+					class_name = extract(html_code, { "list='","'" }, index);
+				}
+			};
+
+			struct pseudo_if_label : public ipseudo_label {
+				pseudo_if_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
+					ipseudo_label(value_type) {
+				}
+				virtual std::string analysis()override {
+					for (auto child : childs) {
+						std::string childValue = child->analysis();
+						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
+					}
+					std::string propName;
+					std::string propValue;
+					std::string symbol;
+					std::vector<std::string> labelValue;
+					//提取标签内容
+					{
+						labelValue = extractList(html_code_tmp, { "}","{" });
+						if (labelValue.empty())
+							return "";
+					}
+					//判断结构体是否有值
+					{
+						if (class_value_list.empty()) {
+							if (labelValue.size() == 2) {
+								return labelValue[1];
+							}
+							return "";
+						}
+					}
+					//获取类名属性名
+					{
+						int index = 0;
+						std::string tmp = extract(html_code_tmp, { "name='","'" }, index);
+						std::string::size_type pos = tmp.find('.');
+						if (pos != std::string::npos) {
+							propName = tmp.substr(pos + 1, tmp.size() - pos - 1);
+						}
+					}
+					//判断类名
+					{
+						if (propName.empty()) {
+							if (labelValue.size() == 2) {
+								return labelValue[1];
+							}
+							return "";
+						}
+					}
+					//判断属性名称是否存在
+					{
+						if (class_value_list[0].find(propName) == class_value_list[0].end()) {
+							if (labelValue.size() == 2) {
+								return labelValue[1];
+							}
+							return "";
+						}
+					}
+					//提取操作符 逻辑对比值
+					{
+						int index = 0;
+						propValue = extract(html_code_tmp, { "value=='","'" }, index);
+						//==
+						if (propValue.empty()) {
+							propValue = extract(html_code_tmp, { "value!='","'" }, index);
+							//!=
+							if (propValue.empty()) {
+								propValue = extract(html_code_tmp, { "value>='","'" }, index);
+								//>=
+								if (propValue.empty()) {
+									propValue = extract(html_code_tmp, { "value<='","'" }, index);
+									//<=
+									if (propValue.empty()) {
+										if (labelValue.size() == 2) {
+											return labelValue[1];
+										}
+										return "";
+									}
+									else
+										symbol = "<=";
+								}
+								else
+									symbol = ">=";
+							}
+							else
+								symbol = "!=";
+						}
+						else
+							symbol = "==";
+					}
+					//判断
+					{
+						if (symbol == "==" && propValue.compare(class_value_list[0][propName]) == 0) {
+							return labelValue[0];
+						}
+						else if (symbol == "!=" && propValue.compare(class_value_list[0][propName]) != 0) {
+							return labelValue[0];
+						}
+						else if (symbol == ">=" && propValue.compare(class_value_list[0][propName]) >= 0) {
+							return labelValue[0];
+						}
+						else if (symbol == "<=" && propValue.compare(class_value_list[0][propName]) <= 0) {
+							return labelValue[0];
+						}
+						else {
+							if (labelValue.size() == 2)
+								return labelValue[1];
+						}
+					}
+					return "";
+				}
+				virtual void analysis_baseinfo() override {
+					html_code_tmp = html_code;
+					for (auto child : childs) {
+						child->analysis_baseinfo();
+					}
+					//获取类名属性名
+					int index = 0;
+					std::string tmp = extract(html_code, { "name='","'" }, index);
+					std::string::size_type pos = tmp.find('.');
+					if (pos != std::string::npos) {
+						class_name = tmp.substr(0, pos);
+					}
+				}
+			};
+
+			struct pseudo_switch_label : public ipseudo_label {
+				pseudo_switch_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
+					ipseudo_label(value_type) {
+				}
+				virtual std::string analysis()override {
+					for (auto child : childs) {
+						std::string childValue = child->analysis();
+						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
+					}
+					std::string propName;
+					std::string labelValueDefault;
+					std::vector<std::string> labelValue;
+
+					//获取类名属性名
+					{
+						int index = 0;
+						std::string tmp = extract(html_code_tmp, { "name='","'" }, index);
+						std::string::size_type pos = tmp.find('.');
+						if (pos != std::string::npos) {
+							propName = tmp.substr(pos + 1, tmp.size() - pos - 1);
+						}
+					}
+
+					//提取标签内容
+					{
+						int index = 0;
+						labelValue = extractList(html_code_tmp, { "{case","/case}" });
+						labelValueDefault = extract(html_code_tmp, { "{default}","{/default}" }, index);
+						if (labelValue.empty() && labelValueDefault.empty()) {
+							return "";
+						}
+						else if (labelValue.empty() && !labelValueDefault.empty()) {
+							if (labelValueDefault.find("#value") != std::string::npos) {
+								if (class_value_list.empty())
+									return "";
+								if (propName.empty())
+									return "";
+								if (class_value_list[0].find(propName) == class_value_list[0].end())
+									return "";
+								return class_value_list[0][propName];
+							}
+							return labelValueDefault;
+						}
+					}
+
+					//判断属性值
+					{
+						if (class_value_list.empty()) {
+							if (labelValueDefault.empty())
+								return "";
+							if (labelValueDefault.find("#value") != std::string::npos)
+								return "";
+							return labelValueDefault;
+						}
+
+						if (propName.empty()) {
+							if (labelValueDefault.empty())
+								return "";
+							if (labelValueDefault.find("#value") != std::string::npos)
+								return "";
+							return labelValueDefault;
+						}
+
+						if (class_value_list[0].find(propName) == class_value_list[0].end()) {
+							if (labelValueDefault.empty())
+								return "";
+							if (labelValueDefault.find("#value") != std::string::npos)
+								return "";
+							return labelValueDefault;
+						}
+					}
+
+					//遍历值
+					{
+						for (auto it : labelValue) {
+							int index = 0;
+							std::string propValue = extract(it, { "value='","'" }, index);
+							if (class_value_list[0][propName] == propValue) {
+								return extract(it, { "}","{" }, index);
+							}
+						}
+					}
+
+					//判断默认值
+					{
+						if (labelValueDefault.empty())
+							return "";
+						if (labelValueDefault.find("#value") != std::string::npos) {
+							return v3::utils::replace(labelValueDefault, "#value", class_value_list[0][propName]);
+						}
+						return labelValueDefault;
+					}
+				}
+				virtual void analysis_baseinfo() override {
+					html_code_tmp = html_code;
+					for (auto child : childs) {
+						child->analysis_baseinfo();
+					}
+					//获取类名属性名
+					int index = 0;
+					std::string tmp = extract(html_code, { "name='","'" }, index);
+					std::string::size_type pos = tmp.find('.');
+					if (pos != std::string::npos) {
+						class_name = tmp.substr(0, pos);
+					}
+				}
+			};
+
+			struct pseudo_file_label : public ipseudo_label {
+				pseudo_file_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
+					ipseudo_label(value_type) {
+				}
+				virtual std::string analysis()override {
+					for (auto child : childs) {
+						std::string childValue = child->analysis();
+						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
+					}
+					int index = 0;
+					std::string path_tmp = extract(html_code_tmp, { "path='","'" }, index);
+					std::filesystem::path path = path_tmp;
+					std::filesystem::path filepath;
+					filepath = http_context::current()->response.get_root_directory();
+					filepath.make_preferred();
+					filepath /= path.make_preferred().relative_path();
+					if (filepath.empty())
+						return "";
+					if (std::filesystem::exists(filepath)) {
+						std::ifstream file(filepath, std::ios::in);
+						if (file.is_open()) {
+							return std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
+						}
+					}
+					return "";
+				}
+				virtual void analysis_baseinfo() override {
+					html_code_tmp = html_code;
+					for (auto child : childs) {
+						child->analysis_baseinfo();
+					}
+				}
+			};
+
+			struct pseudo_extract_class_value {
+				template<typename ..._Args>
+				static std::vector<std::shared_ptr<class_value>> get_class_value(_Args&&...args) {
+					std::vector<std::shared_ptr<class_value>> result;
+					auto tuple = std::forward_as_tuple(std::forward<_Args>(args)...);
+					v3::utils::for_each(tuple, [&](auto& it) {
+						auto value = serialize(it);
+						result.push_back(value); });
+					return result;
+				}
+			private:
+				static std::string get_prop_value(rttr::variant const& value) {
+					std::string result;
+					if (value.get_type() == rttr::type::get<int>()) {
+						result = std::to_string(value.get_value<int>());
+					}
+					else if (value.get_type() == rttr::type::get<std::int64_t>()) {
+						result = std::to_string(value.get_value<std::int64_t>());
+					}
+					else if (value.get_type() == rttr::type::get<float>()) {
+						result = v3::utils::format("{:.2f}", value.get_value<float>());
+					}
+					else if (value.get_type() == rttr::type::get<double>()) {
+						result = v3::utils::format("{:.2f}", value.get_value<double>());
+					}
+					else if (value.get_type() == rttr::type::get<long>()) {
+						result = std::to_string(value.get_value<long>());
+					}
+					else if (value.get_type() == rttr::type::get<bool>()) {
+						if (value.get_value<bool>())
+							result = "true";
+						else
+							result = "false";
+					}
+					else if (value.get_type() == rttr::type::get<std::string>()) {
+						result = value.get_value<std::string>();
+					}
+					else if (value.get_type() == rttr::type::get<v3::datetime>()) {
+						auto t = value.get_value<v3::datetime>();
+						result = t.to_string();
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<int>>()) {
+						auto values = value.get_value<std::vector<int>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += std::to_string(values[i]);
+							}
+							else {
+								result += std::to_string(values[i]) + ",";
+							}
+						}
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<std::int64_t>>()) {
+						auto values = value.get_value<std::vector<std::int64_t>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += std::to_string(values[i]);
+							}
+							else {
+								result += std::to_string(values[i]) + ",";
+							}
+						}
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<float>>()) {
+						auto values = value.get_value<std::vector<float>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += v3::utils::format("{:.2f}", values[i]);
+							}
+							else {
+								result += v3::utils::format("{:.2f}", values[i]) + ",";
+							}
+						}
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<double>>()) {
+						auto values = value.get_value<std::vector<double>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += v3::utils::format("{:.2f}", values[i]);
+							}
+							else {
+								result += v3::utils::format("{:.2f}", values[i]) + ",";
+							}
+						}
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<long>>()) {
+						auto values = value.get_value<std::vector<long>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += std::to_string(values[i]);
+							}
+							else {
+								result += std::to_string(values[i]) + ",";
+							}
+						}
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<bool>>()) {
+						auto values = value.get_value<std::vector<bool>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += values[i] ? "true" : "false";
+							}
+							else {
+								result += values[i] ? "true," : "false,";
+							}
+						}
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<std::string>>()) {
+						auto values = value.get_value<std::vector<std::string>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += values[i];
+							}
+							else {
+								result += values[i] + ",";
+							}
+						}
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<v3::datetime>>()) {
+						auto values = value.get_value<std::vector<v3::datetime>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += values[i].to_string();
+							}
+							else {
+								result += values[i].to_string() + ",";
+							}
+						}
+					}
+					return result;
+				}
+				template<typename _Type>
+				static std::shared_ptr<class_value> serialize(std::vector<std::shared_ptr<_Type>> const& values) {
+					std::vector<_Type> valueTmp;
+					for (auto it : values) {
+						valueTmp.push_back(*it);
+					}
+					return serialize(valueTmp);
+				}
+				template<typename _Type>
+				static std::shared_ptr<class_value> serialize(std::vector<_Type*> values) {
+					std::vector<_Type> valueTmp;
+					for (auto it : values) {
+						valueTmp.push_back(*it);
+					}
+					return serialize(valueTmp);
+				}
+				template<typename _Type>
+				static std::shared_ptr<class_value> serialize(std::vector<_Type> values) {
+					std::shared_ptr<class_value> result(new class_value);
+					rttr::type type = rttr::type::get<_Type>();
+					std::string className(type.get_name());
+					result->class_name = className;
+					result->is_list = true;
+					for (auto it : values) {
+						std::map<std::string, std::string> elem = web_reflect::get_object_value(it);
+						result->class_value.push_back(elem);
+					}
+					return result;
+				}
+				template<typename _Type>
+				static std::shared_ptr<class_value> serialize(std::shared_ptr<_Type> value) {
+					return serialize(*value);
+				}
+				template<typename _Type>
+				static std::shared_ptr<class_value> serialize(_Type* value) {
+					return serialize(*value);
+				}
+				template<typename _Type>
+				static std::shared_ptr<class_value> serialize(_Type value) {
+					std::shared_ptr<class_value> result(new class_value);
+					rttr::type type = rttr::type::get<_Type>();
+					std::string className(type.get_name());
+					result->class_name = className;
+					result->is_list = false;
+					std::map<std::string, std::string> elem = web_reflect::get_object_value(value);
+					result->class_value.push_back(elem);
+					return result;
+				}
+			};
+
+			struct pseudo_extract_label_value {
+				/*
+				* 伪代码结构
+				* 可嵌套 避开关键字 [' }]
+				* ${model name='test_info.userName' value='['${model name='test_info.id' value='[#value]'/}':'启用','false':'禁用'/}
+				*
+				* switch case 中不能存在 #value 属性值  default可以有默认值 可以有固定值
+				* ${switch name='test_info.id'}{case value='1'}<h1>值1</h1>{/case}...{default}<h1>#value</h1>{/default}{/switch}
+				*
+				* if 运算符 == != >= <=
+				* ${if name='test_info.id' value=='100'}<p>判断正确</p>{else}<p>判断错误</p>{/if}
+				*
+				* for for-index 从1开始
+				* ${for item='item' list='test_info'} <td>{item name='item.for-index' value='[#value]'/}</td><td>{item name='item.enable' value='['true':'启用','default':'#value']'/}</td>{/for}
+				*
+				* file path 可以固定 可以嵌套 model设置html路径
+				* ${file path='C:/Users/86158/Desktop/404.html'/}
+				*/
+				static std::vector<std::shared_ptr<ipseudo_label>> analysis(std::string const& html) {
+					std::vector<std::shared_ptr<ipseudo_label>> result;
+					std::pair<std::string, std::string> type = { "${mask","{/mask}" };
+					for (size_t i = 0; i < html.size(); ++i) {
+						if (html.size() > i + type.first.size() &&
+							html[i] == type.first[0] &&
+							html.substr(i, type.first.size()) == type.first) {
+
+							std::string retHtml = nounanalysis(html.substr(i, html.size() - i), result);
+							result[result.size() - 1]->html_code;
+							i += retHtml.size();
+						}
+					}
+					for (auto it : result) {
+						it->analysis_baseinfo();
+					}
+					return result;
+				}
+			private:
+				static std::string nounanalysis(std::string const& html, std::vector<std::shared_ptr<ipseudo_label>>& childs, pseudo_type type = pseudo_type::MASK) {
+					static std::map<pseudo_type, std::pair<std::string, std::string>> g_pseudoLabel = {
+						{
+							pseudo_type::MASK,
+							{"${mask","{/mask}"}
+						},
+						{
+							pseudo_type::MODEL,
+							{"${model","/}"}
+						},
+						{
+							pseudo_type::SWITCH,
+							{"${switch","{/switch}"}
+						},
+						{
+							pseudo_type::IF,
+							{"${if","{/if}"}
+						},
+						{
+							pseudo_type::FOR,
+							{"${for","{/for}"}
+						},
+						{
+							pseudo_type::FILE,
+							{"${file","/}"}
+						}
+					};
+					if (!(html.size() > g_pseudoLabel[type].first.size() &&
+						html.substr(0, g_pseudoLabel[type].first.size()) == g_pseudoLabel[type].first)) {
+						return "";
+					}
+					if (type == pseudo_type::MASK)
+						childs.push_back(std::make_shared<pseudo_mask_label>(*g_pseudoLabel.find(type)));
+					else if (type == pseudo_type::MODEL)
+						childs.push_back(std::make_shared<pseudo_model_label>(*g_pseudoLabel.find(type)));
+					else if (type == pseudo_type::FOR)
+						childs.push_back(std::make_shared<pseudo_for_label>(*g_pseudoLabel.find(type)));
+					else if (type == pseudo_type::IF)
+						childs.push_back(std::make_shared<pseudo_if_label>(*g_pseudoLabel.find(type)));
+					else if (type == pseudo_type::SWITCH)
+						childs.push_back(std::make_shared<pseudo_switch_label>(*g_pseudoLabel.find(type)));
+					else if (type == pseudo_type::FILE)
+						childs.push_back(std::make_shared<pseudo_file_label>(*g_pseudoLabel.find(type)));
+					for (std::string::size_type i = 0; i < html.size(); ++i) {
+						for (auto pseudo : g_pseudoLabel) {
+							if (html.size() > i + pseudo.second.first.size() &&
+								html[i] == pseudo.second.first[0] &&
+								html.substr(i, pseudo.second.first.size()) == pseudo.second.first) {
+								if (i == 0) {
+									break;
+								}
+								else {
+									std::string retHtml = nounanalysis(html.substr(i, html.size() - i), childs[childs.size() - 1]->childs, pseudo.first);
+									childs[childs.size() - 1]->html_code += retHtml;
+									i += retHtml.size();
+								}
+							}
+						}
+						if (type != pseudo_type::NON) {
+							childs[childs.size() - 1]->html_code += html[i];
+						}
+						if (childs[childs.size() - 1]->html_code.size() > g_pseudoLabel[type].second.size() &&
+							childs[childs.size() - 1]->html_code.substr(childs[childs.size() - 1]->html_code.size() - g_pseudoLabel[type].second.size(), g_pseudoLabel[type].second.size()) == g_pseudoLabel[type].second) {
+							return childs[childs.size() - 1]->html_code;
+						}
+					}
+					return "";
+				}
+			};
+
+			enum class from_storage_type {
+				/**
+				 * @brief body
+				*/
+				BODY = 0,
+				/**
+				 * @brief url
+				*/
+				QUERY,
+				/**
+				 * @brief header
+				*/
+				HEADER,
+				/**
+				 * @brief url
+				 */
+				URL
+			};
+
+			enum class argument_type {
+				Json = 0,
+				Multipart,
+				Int,
+				Int64,
+				Float,
+				Double,
+				Long,
+				Bool_,
+				String,
+				DateTime,
+				Binary,
+				VecJson,
+				VecInt,
+				VecInt64,
+				VecFloat,
+				VecDouble,
+				VecLong,
+				VecBool,
+				VecString,
+				VecDateTime
+			};
+
+			enum class http_method {
+				/**
+				 * @brief get
+				*/
+				GET = 0,
+				/**
+				 * @brief post
+				*/
+				POST = 1
+			};
+
+			struct multipart {
+				std::string					content_disposition;
+				std::string					name;
+				std::vector<std::uint8_t>	data;
+				std::string					value;
+				std::string					content_type;
+				std::string					filename;
+				std::string					content_transfer_encoding;
+			};
+
+			struct multipart_value {
+				std::vector<multipart> data;
+				template<typename _Type>
+				_Type value() {
+					_Type result;
+					std::map<std::string, std::string> elem;
+					for (auto value : data) {
+						elem[value.name] = value.value;
+					}
+					web_reflect::set_object_value(result, elem);
+					return result;
+				}
+			};
+
+			struct action_argument {
+				void parameter(http::web_request& request, const rttr::parameter_info& type) {
+					parameter_value_.clear();
+					switch (from_storage_type_) {
+					case from_storage_type::HEADER:  analysis_header(request, type);  return;
+					case from_storage_type::QUERY:   analysis_query(request, type);   return;
+					case from_storage_type::BODY:    analysis_body(request, type);    return;
+					case from_storage_type::URL:     analysis_url(request, type);     return;
+					}
+					throw std::runtime_error("FormStorageType:错误!");
+				}
+				/**
+				 * @brief 参数名称
+				*/
+				std::string					parameter_name_;
+				/**
+				 * @brief 参数
+				*/
+				rttr::variant				parameter_value_;
+				/**
+				 * @brief 数据类型
+				*/
+				argument_type				argument_type_ = argument_type::Binary;
+				/**
+				 * @brief 表单存储类型
+				*/
+				from_storage_type			from_storage_type_ = from_storage_type::QUERY;
+			private:
+				/**
+				 * @brief 解析协议头
+				 * @param request
+				 * @param type
+				*/
+				void analysis_header(http::web_request& request, const rttr::parameter_info& type) {
+					std::map<std::string, std::string> headers;
+					for (auto& it : request) {
+						std::string name(it.name_string().begin(), it.name_string().end());
+						std::string value(it.value().begin(), it.value().end());
+						headers[name] = value;
+					}
+					if (headers.find(parameter_name_) == headers.end())
+						throw std::runtime_error("解析协议头参数错误!");
+					convert(headers[parameter_name_], type);
+				}
+				/**
+				 * @brief 解析url参数
+				 * @param request
+				 * @param type
+				*/
+				void analysis_query(http::web_request& request, const rttr::parameter_info& type) {
+					std::string query(request.query().begin(), request.query().end());
+					std::map<std::string, std::string>  querys = v3::utils::split_http_form(query);
+					if (querys.find(parameter_name_) == querys.end())
+						throw std::runtime_error("解析Query参数错误!");
+					convert(querys[parameter_name_], type);
+				}
+				/**
+				 * @brief 解析BODY
+				 * @param request
+				 * @param type
+				*/
+				void analysis_body(http::web_request& request, const rttr::parameter_info& type) {
+					if (type.get_type() == rttr::type::get<multipart_value>()) {
+						multipart_value parameter;
+						auto multipartValue = request.get_multipart();
+						for (auto it = multipartValue.begin(); it != multipartValue.end(); ++it) {
+							multipart item;
+							item.content_disposition = it->content_disposition();
+							item.name = it->name();
+							auto valueTmp = it->value();
+							item.data.insert(item.data.end(), valueTmp.begin(), valueTmp.end());
+							if (it->filename().empty()) {
+								try {
+									item.value = it->value();
+								}
+								catch (...) {}
+							}
+							item.content_type = it->content_type();
+							item.filename = it->filename();
+							item.content_transfer_encoding = it->content_transfer_encoding();
+							parameter.data.push_back(item);
+						}
+						parameter_value_ = parameter;
+					}
+					else if (parameter_name_.empty()) {
+						convert(std::string(request.body().begin(), request.body().end()), type);
+					}
+					else {
+						std::string body(request.body().begin(), request.body().end());
+						std::map<std::string, std::string> bodys = v3::utils::split_http_form(body);
+						if (bodys.find(parameter_name_) == bodys.end())
+							throw std::runtime_error("解析Body参数错误!");
+						convert(bodys[parameter_name_], type);
+					}
+				}
+				/**
+				 * @brief url
+				 * @param request
+				 * @param type
+				 */
+				void analysis_url(http::web_request& request, const rttr::parameter_info& type) {
+					std::string query(request.find("http_route_parameter")->value());
+					std::map<std::string, std::string>  querys = v3::utils::split_http_form(query);
+					if (querys.find(parameter_name_) == querys.end())
+						throw std::runtime_error("解析Query参数错误!");
+					convert(querys[parameter_name_], type);
+				}
+				/**
+				 * @brief 数据转换
+				 * @param data
+				 * @param type
+				*/
+				void convert(std::string_view data, const rttr::parameter_info& type) {
+					try {
+						switch (argument_type_) {
+						case argument_type::Json: {
+							parameter_value_ = type.get_type().create();
+							v3::json_convert::deserialize(std::string(data.begin(), data.end()), parameter_value_);
+							return;
+						}
+						case argument_type::Multipart: {
+							return;
+						}
+						case argument_type::Int: {
+							parameter_value_ = std::atoi(std::string(data.begin(), data.end()).c_str());
+							return;
+						}
+						case argument_type::Int64: {
+							parameter_value_ = std::atoll(std::string(data.begin(), data.end()).c_str());
+							return;
+						}
+						case argument_type::Float: {
+							parameter_value_ = std::atof(std::string(data.begin(), data.end()).c_str());
+							return;
+						}
+						case argument_type::Double: {
+							parameter_value_ = std::atof(std::string(data.begin(), data.end()).c_str());
+							return;
+						}
+						case argument_type::Long: {
+							parameter_value_ = std::atol(std::string(data.begin(), data.end()).c_str());
+							return;
+						}
+						case argument_type::Bool_: {
+							std::string tmpValue(data.begin(), data.end());
+							parameter_value_ = tmpValue == "1" || tmpValue == "true" || tmpValue == "TRUE" || tmpValue == "True";
+							return;
+						}
+						case argument_type::String: {
+							parameter_value_ = std::string(data.begin(), data.end());
+							return;
+						}
+						case argument_type::DateTime: {
+							parameter_value_ = datetime(std::string(data.begin(), data.end()));
+							return;
+						}
+						case argument_type::Binary: {
+							parameter_value_ = std::vector<std::uint8_t>(data.begin(), data.end());
+							return;
+						}
+						case argument_type::VecInt: {
+							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							std::vector<int> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atoi(vecIt.c_str()));
+							}
+							parameter_value_ = vecValue;
+							return;
+						}
+						case argument_type::VecInt64: {
+							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							std::vector<std::int64_t> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atoll(vecIt.c_str()));
+							}
+							parameter_value_ = vecValue;
+							return;
+						}
+						case argument_type::VecFloat: {
+							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							std::vector<float> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atof(vecIt.c_str()));
+							}
+							parameter_value_ = vecValue;
+							return;
+						}
+						case argument_type::VecDouble: {
+							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							std::vector<double> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atof(vecIt.c_str()));
+							}
+							parameter_value_ = vecValue;
+							return;
+						}
+						case argument_type::VecLong: {
+							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							std::vector<long> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atol(vecIt.c_str()));
+							}
+							parameter_value_ = vecValue;
+							return;
+						}
+						case argument_type::VecBool: {
+							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							std::vector<bool> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(vecIt == "1" || vecIt == "true" || vecIt == "TRUE" || vecIt == "True");
+							}
+							parameter_value_ = vecValue;
+							return;
+						}
+						case argument_type::VecString: {
+							std::vector<std::string> vecValue = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							parameter_value_ = vecValue;
+							return;
+						}
+						case argument_type::VecDateTime: {
+							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							std::vector<datetime> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(datetime(vecIt));
+							}
+							parameter_value_ = vecValue;
+							return;
+						}
+						}
+					}
+					catch (...) {
+						throw std::runtime_error("解析参数错误");
+					}
+				}
+			};
+
+			struct controller;
+
+			struct controller_action {
+				/**
+				 * @brief 执行动作
+				 * @param request
+				*/
+				rttr::variant invoke(http::web_request& request, rttr::variant& variant, rttr::type const& controller_type) {
+					auto http_current_ptr = http_context::current();
+					//判断contentType
+					std::string content_type = "application/x-www-form-urlencoded";
+					if (request.find(http::field::content_type) != request.end()) {
+						content_type = std::string(request.find(http::field::content_type)->value().begin(), request.find(http::field::content_type)->value().end());
+					}
+					if (content_type.find(content_type) == std::string::npos) {
+						throw std::runtime_error("Content-Type:错误!");
+					}
+					//判断method
+					if (!((method == http_method::GET && request.method() == http::verb::get) || (method == http_method::POST && request.method() == http::verb::post))) {
+						throw std::runtime_error("Method:错误!");
+					}
+					std::vector<rttr::method> find_method;
+					for (auto& it : controller_type.get_methods()) {
+						if (it.get_name() == action_name && it.get_parameter_infos().size() == arguments.size()) {
+							find_method.push_back(it);
+							break;
+						}
+					}
+					if (find_method.empty())
+						throw std::runtime_error("Action:错误!");
+					std::vector<rttr::argument> parameters;
+					std::vector<rttr::variant> variantParameters;
+					{
+						std::lock_guard<std::mutex> locker(mux);
+						for (auto& it : find_method[0].get_parameter_infos()) {
+							arguments[it.get_index()]->parameter(request, it);
+						}
+						for (auto& it : arguments) {
+							variantParameters.push_back(it->parameter_value_);
+						}
+					}
+					for (auto& it : variantParameters) {
+						parameters.push_back(it);
+					}
+					return controller_type.invoke(action_name, variant, parameters);
+				}
+				/**
+				 * @brief 身份验证
+				*/
+				bool											authen = true;
+				/**
+				 * @brief 未登录跳转
+				*/
+				std::string										authen_jump;
+				/**
+				 * @brief 方法名称
+				*/
+				std::string										action_name;
+				/**
+				 * @brief 方式
+				*/
+				http_method										method = http_method::GET;
+				/**
+				 * @brief 数据类型
+				*/
+				std::string										content_type = "application/x-www-form-urlencoded";
+				/**
+				 * @brief 动作类型
+				*/
+				std::string										action_type;
+				/**
+				 * @brief 文件映射
+				*/
+				std::string										file_mapping;
+				/**
+				 * @brief 参数
+				*/
+				std::vector<std::shared_ptr<action_argument>>	arguments;
+				/**
+				 * @brief 控制器
+				*/
+				std::shared_ptr<controller>						parent;
+			private:
+				/**
+				 * @brief 锁
+				*/
+				std::mutex										mux;
+			};
+
+			struct controller {
+				rttr::variant invoke(http::web_request& request) {
+					std::string key(request.find("http_route_key")->value());
+					if (!actions.contains(key))
+						throw std::runtime_error("Action:不存在!");
+					rttr::type type = rttr::type::get_by_name(controller_name);
+					if (!variant.is_valid())
+						variant = type.create();
+					return actions[key]->invoke(request, variant, type);
+				}
+				/**
+				 * @brief 控制器名称
+				*/
+				std::string controller_name;
+				/**
+				 * @brief 动作列表 路由 动作
+				*/
+				std::map<std::string, std::shared_ptr<controller_action>> actions;
+			private:
+				/**
+				 * @brief 对象
+				*/
+				rttr::variant variant;
+			};
+
+			struct mvc_route {
+				bool contains(http::web_request& req) {
+					std::string key;
+					std::string route(req.find("http_route")->value());
+					if (contains(route, key)) {
+						std::size_t index = key.find('<');
+						std::vector<std::string> params;
+						if (std::string::npos != index) {
+							auto keys = v3::utils::split(key.substr(index), "/");
+							auto values = v3::utils::split(route.substr(index), "/");
+							for (int i = 0; i < keys.size() && i < values.size(); ++i) {
+								params.push_back(keys[i].substr(1, keys[i].size() - 2) + "=" + values[i]);
+							}
+						}
+						req.insert("http_route_key", key);
+						req.insert("http_route_parameter", v3::utils::join(params, "&"));
+						return true;
+					}
+					return false;
+				}
+				bool contains(std::string const& route) {
+					std::string key;
+					return contains(route, key);
+				}
+				void add(std::string const& route, std::shared_ptr<controller> value) {
+					routes_[route] = value;
+				}
+				std::shared_ptr<controller>& find(std::string const& route) {
+					std::string key;
+					if (contains(route, key)) {
+						return routes_[key];
+					}
+					throw std::runtime_error("key does not exist");
+				}
+				std::shared_ptr<controller>& operator[](std::string const& route) {
+					return find(route);
+				}
+				std::shared_ptr<controller>& operator[](http::web_request& req) {
+					return find(std::string(req.find("http_route_key")->value()));
+				}
+			private:
+				bool contains(std::string const& route, std::string& result) {
+					if (routes_.contains(route)) {
+						result = route;
+						return true;
+					}
+					else {
+						int slash_count = std::count(route.begin(), route.end(), '/');
+						for (auto& [first, second] : routes_) {
+							std::size_t index = first.find('<');
+							if (std::count(first.begin(), first.end(), '/') == slash_count && index != std::string::npos) {
+								if (first.substr(0, index) == route.substr(0, index)) {
+									result = first;
+									return true;
+								}
+							}
+						}
+						return false;
+					}
+				}
+			private:
+				std::map<std::string, std::shared_ptr<controller>> routes_;
+			};
+
+			struct MVC_API ico_controller {
+				/**
+				 * @brief 注册
+				*/
+				static void attach(std::shared_ptr<controller> controller) {
+					for (auto& [first, second] : controller->actions) {
+						controllers_.add(first, controller);
+					}
+				}
+				/**
+				 * @brief
+				 * @param url
+				 * @return
+				*/
+				static std::shared_ptr<controller> resolve(http::web_request& req) {
+					if (controllers_.contains(req)) {
+						return controllers_[req];
+					}
+					return nullptr;
+				}
+			private:
+				/**
+				 * @brief
+				*/
+				static mvc_route controllers_;
+			};
+			
+			struct web_base_response {
+				void set_header(std::string_view name, std::string_view value) {
+					auto& response = http_context::current()->response;
+					response.set(name, value);
+				}
+				void set_header(http::field field, std::string_view value) {
+					auto& response = http_context::current()->response;
+					response.set(field, value);
+				}
+				void set_value(std::string_view value) {
+					auto& response = http_context::current()->response;
+					response.body().file().close();
+					response.body().text() = std::move(value);
+					auto const size = response.body().size();
+					response.content_length(size);
+				}
+				void set_value(std::vector<std::uint8_t> const& value) {
+					auto& response = http_context::current()->response;
+					response.body().file().close();
+					response.body().text() = std::string((char*)&value[0], value.size());
+					auto const size = response.body().size();
+					response.content_length(size);
+				}
+				void set_status(http::status status = http::status::ok) {
+					auto& response = http_context::current()->response;
+					response.result(status);
+				}
+				std::filesystem::path get_root_directory() {
+					auto& response = http_context::current()->response;
+					return response.get_root_directory();
+				}
+				http::status get_status() {
+					auto& response = http_context::current()->response;
+					return response.result();
+				}
+				std::string get_value() {
+					auto& response = http_context::current()->response;
+					return response.body().text();
+				}
+				void prepare_payload() {
+					auto& response = http_context::current()->response;
+					response.prepare_payload();
+				}
+				void chunked(bool value) {
+					auto& response = http_context::current()->response;
+					response.chunked(value);
+				}
+				void set_server(std::string_view value = BEAST_VERSION_STRING) {
+					auto& response = http_context::current()->response;
+					response.set(http::field::server, value);
+				}
+				void set_version(int ver = 11) {
+					auto& response = http_context::current()->response;
+					response.version(ver);
+				}
+				void fill_file(std::filesystem::path const& path, http::status status = http::status::ok) {
+					auto& response = http_context::current()->response;
+					if (path.c_str()[0] == '/' || path.c_str()[0] == '\\') {
+						response.fill_file(path, status);
+					}
+					else {
+						response.fill_file("/" + path.string(), status);
+					}
+				}
+				void fill_html(std::string const& html, http::status status = http::status::ok) {
+					auto& response = http_context::current()->response;
+					response.fill_html(html, status);
+				}
+				void fill_json(std::string const& json, http::status status = http::status::ok) {
+					auto& response = http_context::current()->response;
+					response.fill_json(json, status);
+				}
+				void fill_page(std::string const& value, http::status status = http::status::ok) {
+					auto& response = http_context::current()->response;
+					response.fill_page(status, value);
+				}
+				void fill_text(std::string const& text, http::status status = http::status::ok) {
+					auto& response = http_context::current()->response;
+					response.fill_text(text, status);
+				}
+				void fill_jump(std::string const& url) {
+					set_header(http::field::content_type, http::extension_to_mimetype("html"));
+					set_header(http::field::location, url);
+					set_status(http::status::found);
+				}
+				void fill_stream(std::vector<std::uint8_t> const& data, std::string const& extension, http::status status = http::status::ok) {
+					set_header("Content-Type", http::extension_to_mimetype(extension));
+					set_value(data);
+					set_status(status);
+				}
+				void fill_download(std::filesystem::path const& path, http::status status = http::status::ok) {
+					set_header(http::field::content_type, "application/octet-stream");
+					set_header(http::field::content_disposition, v3::utils::format("attachment; filename={}", path.filename().string()));
+				}
+				void fill_download(std::filesystem::path const& path, std::string const& filename, http::status status = http::status::ok) {
+					set_header(http::field::content_type, "application/octet-stream");
+					set_header(http::field::content_disposition, v3::utils::format("attachment; filename={}", filename));
+				}
+				void fill_view(http::status status = http::status::ok) {
+					fill_file(get_filename(), status);
+				}
+				std::filesystem::path get_filename() {
+					return mvc::http_context::current()->get_controller_action()->file_mapping;
+				}
+			};
+
+			struct web_result_response : public web_base_response {};
+
+			struct unknown_response : public web_base_response {
+				unknown_response(std::string const& text) {
+					set_value(text);
+					set_status(http::status::unknown);
+				}
+				virtual ~unknown_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct jump_response : public web_base_response {
+				jump_response(std::string const& url) {
+					if (!url.empty()) {
+						if (url[0] != '/')
+							fill_jump("/" + url);
+					}
+					else {
+						fill_jump(url);
+					}
+				}
+				virtual ~jump_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct text_response : public web_base_response {
+				text_response(std::string const& text, http::status status = http::status::ok) {
+					fill_text(text, status);
+				}
+				virtual ~text_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct html_response : public web_base_response {
+				html_response(std::string const& html, http::status status = http::status::ok) {
+					fill_html(html, status);
+				}
+				virtual ~html_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct file_response : public web_base_response {
+				file_response() {
+					fill_file(get_filename());
+				}
+				file_response(http::status status = http::status::ok) {
+					fill_file(get_filename(), status);
+				}
+				file_response(std::filesystem::path const& path, http::status status = http::status::ok) {
+					fill_file(path, status);
+				}
+				virtual ~file_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct json_response : public web_base_response {
+				json_response(std::string const& json) {
+					fill_json(json);
+				}
+				json_response(char* json) :
+					json_response(std::string(json)) {
+				}
+				json_response(const char* json) :
+					json_response(std::string(json)) {
+				}
+				template<typename _Type>
+				json_response(_Type const& value) {
+					fill_json(v3::json_convert::serialize(value));
+				}
+				virtual~json_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct stream_response : public web_base_response {
+				stream_response(std::vector<std::uint8_t> const& data, std::string const& extension, http::status status = http::status::ok) {
+					fill_stream(data, extension, status);
+				}
+				virtual~stream_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct download_response : public web_base_response {
+				download_response(std::filesystem::path const& path, http::status status = http::status::ok) {
+					fill_download(path, status);
+				}
+				download_response(std::filesystem::path const& path, std::string const& filename, http::status status = http::status::ok) {
+					fill_download(path, filename, status);
+				}
+				virtual~download_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct view : public web_base_response {
+				virtual ~view() {
+				}
+				view() :
+					web_base_response() {
+					fill_view();
+				}
+				view(std::string const& path) :
+					web_base_response() {
+					fill_file(path);
+				}
+				template<typename ..._Args>
+				view(_Args&& ...args) {
+					std::filesystem::path path = get_filename();
+					std::filesystem::path filepath;
+					filepath = http_context::current()->response.get_root_directory();
+					filepath.make_preferred();
+					filepath /= path.make_preferred().relative_path();
+					std::vector<std::uint8_t> value;
+					std::ifstream file(filepath, std::ios::in | std::ios::binary);
+					if (file.is_open()) {
+						file.seekg(0, std::ios::end);
+						int file_size = file.tellg();
+						file.seekg(0, std::ios::beg);
+						value.resize(file_size);
+						file.read((char*)&value[0], file_size);
+						file.close();
+					}
+					std::string html(value.begin(), value.end());
+					auto label_value_list = pseudo_extract_label_value::analysis(html);
+					if (!label_value_list.empty()) {
+						auto classValueList = pseudo_extract_class_value::get_class_value(std::forward<_Args>(args)...);
+						label_value_list[0]->set_class_value(classValueList);
+						html = label_value_list[0]->analysis();
+						fill_html(html);
+					}
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			template<int _Width = 100, int _Height = 38, int _Length = 4, int _Line = 2, int _Spot = 200>
+			struct captcha_response : public v3::mvc::web_base_response {
+				captcha_response(std::string const& session_key = "code") :
+					session_key_(session_key) {
+				}
+				virtual ~captcha_response() {
+				}
+				operator v3::mvc::web_result_response() {
+					//验证码
+					std::string captcha_code = generate_captcha_digits();
+					http_context::current()->add_session(session_key_, captcha_code);
+					std::vector<std::uint8_t> img_vec = generate_captcha_image(captcha_code);
+					return v3::mvc::stream_response(img_vec, "bmp");
+				}
+			private:
+				class CImage : public cimg_library::CImg<unsigned char> {
+				public:
+					CImage(const cimg_library::CImg<unsigned char>& img) :
+						cimg_library::CImg<unsigned char>(img) {}
+					cimg_library::CImg<unsigned char>& save_memory_bmp(std::vector<std::uint8_t>& result) {
+						cimg_library::CImg<ucharT> header(54, 1, 1, 1, 0);
+						unsigned char align_buf[4] = {};
+						const unsigned int
+							align = (4 - (3 * _width) % 4) % 4,
+							buf_size = (3 * _width + align) * height(),
+							file_size = 54 + buf_size;
+						header[0] = 'B'; header[1] = 'M';
+						header[0x02] = file_size & 0xFF;
+						header[0x03] = (file_size >> 8) & 0xFF;
+						header[0x04] = (file_size >> 16) & 0xFF;
+						header[0x05] = (file_size >> 24) & 0xFF;
+						header[0x0A] = 0x36;
+						header[0x0E] = 0x28;
+						header[0x12] = _width & 0xFF;
+						header[0x13] = (_width >> 8) & 0xFF;
+						header[0x14] = (_width >> 16) & 0xFF;
+						header[0x15] = (_width >> 24) & 0xFF;
+						header[0x16] = _height & 0xFF;
+						header[0x17] = (_height >> 8) & 0xFF;
+						header[0x18] = (_height >> 16) & 0xFF;
+						header[0x19] = (_height >> 24) & 0xFF;
+						header[0x1A] = 1;
+						header[0x1B] = 0;
+						header[0x1C] = 24;
+						header[0x1D] = 0;
+						header[0x22] = buf_size & 0xFF;
+						header[0x23] = (buf_size >> 8) & 0xFF;
+						header[0x24] = (buf_size >> 16) & 0xFF;
+						header[0x25] = (buf_size >> 24) & 0xFF;
+						header[0x27] = 0x1;
+						header[0x2B] = 0x1;
+						result.insert(result.end(), reinterpret_cast<std::uint8_t*>(header._data), reinterpret_cast<std::uint8_t*>(header._data) + 64);
+						const unsigned char
+							* ptr_r = data(0, _height - 1, 0, 0),
+							* ptr_g = (_spectrum >= 2) ? data(0, _height - 1, 0, 1) : 0,
+							* ptr_b = (_spectrum >= 3) ? data(0, _height - 1, 0, 2) : 0;
+						switch (_spectrum) {
+						case 1: {
+							cimg_forY(*this, y) {
+								cimg_forX(*this, x) {
+									const unsigned char val = (unsigned char)*(ptr_r++);
+									result.push_back(val); result.push_back(val); result.push_back(val);
+								}
+								result.insert(result.end(), reinterpret_cast<std::uint8_t*>(align_buf), reinterpret_cast<std::uint8_t*>(align_buf) + align);
+								ptr_r -= 2 * _width;
+							}
+						} break;
+						case 2: {
+							cimg_forY(*this, y) {
+								cimg_forX(*this, x) {
+									result.push_back(0);
+									result.push_back((unsigned char)(*(ptr_g++)));
+									result.push_back((unsigned char)(*(ptr_r++)));
+								}
+								result.insert(result.end(), reinterpret_cast<std::uint8_t*>(align_buf), reinterpret_cast<std::uint8_t*>(align_buf) + align);
+								ptr_r -= 2 * _width; ptr_g -= 2 * _width;
+							}
+						} break;
+						default: {
+							cimg_forY(*this, y) {
+								cimg_forX(*this, x) {
+									result.push_back((unsigned char)(*(ptr_b++)));
+									result.push_back((unsigned char)(*(ptr_g++)));
+									result.push_back((unsigned char)(*(ptr_r++)));
+								}
+								result.insert(result.end(), reinterpret_cast<std::uint8_t*>(align_buf), reinterpret_cast<std::uint8_t*>(align_buf) + align);
+								ptr_r -= 2 * _width; ptr_g -= 2 * _width; ptr_b -= 2 * _width;
+							}
+						}
+						}
+						return *this;
+					}
+				};
+			private:
+				//获取验证码
+				std::string generate_captcha_digits() {
+					static const char data_character[] = "23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ\0";
+					int min = 0;
+					int max = std::strlen(data_character) - 1;
+					std::string result;
+					for (int i = 0; i < _Length; ++i) {
+						result += data_character[v3::utils::random(min, max)];
+					}
+					return result;
+				}
+				//生成随机颜色
+				unsigned char* generate_random_color() {
+					static unsigned char colors[][3] = {
+						{47,79,79     },
+						{105,105,105  },
+						{0,0,128      },
+						{100,149,237  },
+						{72,61,139    },
+						{106,90,205   },
+						{123,104,238  },
+						{132,112,255  },
+						{65,105,225   },
+						{85,107,47    },
+						{107,142,35   },
+						{205,92,92    },
+						{160,82,45    },
+						{178,34,34    },
+						{255,69,0     },
+						{176,48,96    },
+						{160,32,240   },
+						{139,137,137  },
+						{0,139,139    },
+						{139,0,0      },
+						{139,0,139    },
+						{154,50,205   },
+						{238,64,0     },
+						{0,139,69     } };
+					return colors[v3::utils::random(0, sizeof(colors) / sizeof(colors[0]) - 1)];
+				}
+				//生成字体大小,位置
+				std::vector<std::tuple<int, int, int>> generate_font_size() {
+					std::vector<std::tuple<int, int, int>> result;
+					int s_width = _Width / _Length;
+					int s_height = _Height;
+					for (int i = 0; i < _Length; ++i) {
+						int x = 0, y = 0, s = 0;
+						double font_centre_pos = 0.0;
+						if (s_width > s_height) {
+							s = v3::utils::random(double(s_height) - double(s_height) * 0.2, double(s_height) * 1.2);
+						}
+						else {
+							s = v3::utils::random(double(s_width) - double(s_width) * 0.2, double(s_width) * 1.2);
+						}
+						font_centre_pos = double(s) * 0.8;
+						x = v3::utils::random(0, double(s_width) - font_centre_pos);
+						y = v3::utils::random(0, double(s_height) - font_centre_pos);
+						result.push_back(std::make_tuple(s, x, y));
+					}
+					return result;
+				}
+				//验证码图片
+				std::vector<std::uint8_t> generate_captcha_image(std::string const& code) {
+					std::vector<std::uint8_t> result;
+					cimg_library::CImg<unsigned char> image(_Width, _Height, 1, 3, 255);  // 创建一个白色背景的图像
+					int s_width = _Width / _Length;
+					int s_height = _Height;
+					std::vector<std::tuple<int, int, int>> font_info = generate_font_size();
+					char c[2] = { 0 };
+					//绘制验证码
+					for (int i = 0; i < _Length; ++i) {
+						c[0] = code[i];
+						image.draw_text(i * s_width + std::get<1>(font_info[i]), std::get<2>(font_info[i]), c, generate_random_color(), 0, 1, std::get<0>(font_info[i])).width();
+					}
+					//绘制干扰线
+					for (int i = 0; i < _Line; ++i) {
+						int x1 = std::rand() % _Width;
+						int y1 = std::rand() % _Height;
+						int x2 = std::rand() % _Width;
+						int y2 = std::rand() % _Height;
+						// 生成随机颜色
+						image.draw_line(x1, y1, x2, y2, generate_random_color());
+					}
+					//绘制干扰点
+					for (int i = 0; i < _Spot; ++i) {
+						int x = std::rand() % _Width;
+						int y = std::rand() % _Height;
+						// 生成随机颜色
+						image.draw_point(x, y, generate_random_color());
+					}
+
+					//扭曲图像
+					cimg_library::CImg<unsigned char> distorted_image(_Width, _Height, 1, 3, 255);
+					cimg_forXY(image, xx, yy) {
+						int new_xx = xx + static_cast<int>(1.32 * sin(2 * 3.14 * yy * 0.045));
+						int new_yy = yy + static_cast<int>(1.42 * sin(2 * 3.14 * xx * 0.062));
+						if (new_xx >= 0 && new_xx < _Width && new_yy >= 0 && new_yy < _Height) {
+							distorted_image(xx, yy, 0, 0) = image(new_xx, new_yy, 0, 0);
+							distorted_image(xx, yy, 0, 1) = image(new_xx, new_yy, 0, 1);
+							distorted_image(xx, yy, 0, 2) = image(new_xx, new_yy, 0, 2);
+						}
+					}
+					CImage(distorted_image).save_memory_bmp(result);
+					return result;
+				}
+			private:
+				std::string session_key_;
+			};
+
+			class http_server_t {
+			public:
+				http_server_t() {
+					server_.bind<http::verb::post, http::verb::get>(std::string("/*"), &http_server_t::on_base_request, this);
+				}
+				bool start(std::string const& ip, int port) {
+					return server_.start(ip, port);
+				}
+				void stop() {
+					server_.stop();
+				}
+				void set_root_directory(std::filesystem::path const& path) {
+					server_.set_root_directory(path);
+				}
+			protected:
+				virtual void on_request(http::web_request& req, http::web_response& rep) = 0;
+			private:
+				void on_base_request(std::shared_ptr<asio2::http_session>& session_ptr, http::web_request& req, http::web_response& rep) {
+					on_request(req, rep);
+				}
+			private:
+				asio2::http_server server_;
+			};
+
+			class https_server_t {
+			public:
+				https_server_t() {
+					server_.bind<http::verb::post, http::verb::get>("/*", &https_server_t::on_base_request, this);
+				}
+				bool start(std::string const& ip, int port) {
+					return server_.start(ip, port);
+				}
+				void stop() {
+					server_.stop();
+				}
+				void set_root_directory(std::filesystem::path const& path) {
+					server_.set_root_directory(path);
+				}
+				void set_cert_file(std::string const& ca_cert_file, std::string const& private_cert_file, std::string const& private_key_file, std::string const& private_password) {
+					server_.set_cert_file(ca_cert_file, private_cert_file, private_key_file, private_password);
+				}
+			protected:
+				virtual void on_request(http::web_request& req, http::web_response& rep) = 0;
+			private:
+				void on_base_request(std::shared_ptr<asio2::https_session>& session_ptr, http::web_request& req, http::web_response& rep) {
+					on_request(req, rep);
+				}
+			private:
+				asio2::https_server server_;
+			};
+
+			template<typename _Before, typename _Err, typename _After, typename _TypeBase>
+			class http_server_base : public _TypeBase {
+			public:
+				http_server_base() :
+					_TypeBase() {
+				}
+			private:
+				virtual void on_request(http::web_request& req, http::web_response& rep)override {
+					http_context_gc http_context(req, rep);
+					try {
+						req.insert("http_route", std::string(req.path()).substr(1));
+						std::shared_ptr<controller> controller = v3::mvc::ico_controller::resolve(req);
+						std::string key(req.find("http_route_key")->value());
+						http_context::current()->set_controller_action((bool)controller ? controller->actions[key] : nullptr);
+						if (before_.before((bool)controller ? controller->actions[key] : nullptr, req, rep)) {
+							rttr::variant variant = controller->invoke(req);
+							if (variant.is_valid()) {
+								auto response = variant.get_value<web_base_response>();
+								response.set_version();
+								response.set_server();
+								response.chunked(true);
+								response.prepare_payload();
+							}
+						}
+						//文件
+						else {
+							rep.fill_file(req.path());
+							rep.set(http::field::cache_control, "max-age=31536000");
+							rep.chunked(true);
+						}
+					}
+					catch (unknown_response const&) {
+					}
+					catch (jump_response const&) {
+					}
+					catch (text_response const&) {
+					}
+					catch (html_response const&) {
+					}
+					catch (file_response const&) {
+					}
+					catch (json_response const&) {
+					}
+					catch (std::exception const& ec) {
+						err_.error(ec.what(), req, rep);
+					}
+					catch (...) {
+						err_.error("未知异常", req, rep);
+					}
+					after_.after(req, rep);
+				}
+			private:
+				_Before	before_;
+				_Err	err_;
+				_After	after_;
+			};
+
+			template<typename _Before, typename _Err, typename _After>
+			using http_server = http_server_base<_Before, _Err, _After, http_server_t>;
+
+			template<typename _Before, typename _Err, typename _After>
+			using https_server = http_server_base<_Before, _Err, _After, https_server_t>;
+		}
+	}
+}

+ 2 - 0
robot/robotics/json.hpp

@@ -14,6 +14,8 @@
 #include <nlohmann/json.hpp>
 //rttr
 #include <rttr/registration>
+//robotics
+#include "datetime.hpp"
 
 namespace robotics {
 	namespace v3 {

+ 1 - 2743
robot/robotics/mvc.hpp

@@ -8,2747 +8,5 @@
 *
 */
 #pragma once
-//asio2
-#include <asio2/asio2.hpp>
 //robotics
-#include "utils.hpp"
-#include "json.hpp"
-#include "CImg.h"
-
-namespace robotics {
-	namespace v3 {
-		namespace mvc {
-			class web_reflect {
-			public:
-				/**
-				 * @brief
-				 * @param obj
-				 */
-				static std::map<std::string, std::string> get_object_value(rttr::instance obj) {
-					std::map<std::string, std::string> result;
-					auto propertys = obj.get_type().get_properties();
-					for (auto& property : propertys) {
-						std::string propName(property.get_name());
-						rttr::variant propValue = property.get_value(obj);
-						rttr::type propType = property.get_type();
-						if (propType == rttr::type::get<int>()) {
-							result[propName] = std::to_string(propValue.get_value<int>());
-						}
-						else if (propType == rttr::type::get<std::int64_t>()) {
-							result[propName] = std::to_string(propValue.get_value<std::int64_t>());
-						}
-						else if (propType == rttr::type::get<float>()) {
-							result[propName] = v3::utils::format("{:.2f}", propValue.get_value<float>());
-						}
-						else if (propType == rttr::type::get<double>()) {
-							result[propName] = v3::utils::format("{:.2f}", propValue.get_value<double>());
-						}
-						else if (propType == rttr::type::get<long>()) {
-							result[propName] = std::to_string(propValue.get_value<long>());
-						}
-						else if (propType == rttr::type::get<bool>()) {
-							result[propName] = propValue.get_value<bool>() ? "true" : "false";
-						}
-						else if (propType == rttr::type::get<std::string>()) {
-							result[propName] = propValue.get_value<std::string>();
-						}
-						else if (propType == rttr::type::get<v3::datetime>()) {
-							result[propName] = propValue.get_value<v3::datetime>().to_string();
-						}
-						else if (propType == rttr::type::get<std::vector<int>>()) {
-							auto vecValue = propValue.get_value<std::vector<int>>();
-							result[propName] = v3::utils::join(vecValue, ",");
-						}
-						else if (propType == rttr::type::get<std::vector<std::int64_t>>()) {
-							auto vecValue = propValue.get_value<std::vector<std::int64_t>>();
-							result[propName] = v3::utils::join(vecValue, ",");
-						}
-						else if (propType == rttr::type::get<std::vector<float>>()) {
-							auto vecValue = propValue.get_value<std::vector<float>>();
-							result[propName] = v3::utils::join(vecValue, ",");
-						}
-						else if (propType == rttr::type::get<std::vector<double>>()) {
-							auto vecValue = propValue.get_value<std::vector<double>>();
-							result[propName] = v3::utils::join(vecValue, ",");
-						}
-						else if (propType == rttr::type::get<std::vector<long>>()) {
-							auto vecValue = propValue.get_value<std::vector<long>>();
-							result[propName] = v3::utils::join(vecValue, ",");
-						}
-						else if (propType == rttr::type::get<std::vector<bool>>()) {
-							auto vecValue = propValue.get_value<std::vector<bool>>();
-							result[propName] = v3::utils::join(vecValue, ",");
-						}
-						else if (propType == rttr::type::get<std::vector<std::string>>()) {
-							auto vecValue = propValue.get_value<std::vector<std::string>>();
-							result[propName] = v3::utils::join(vecValue, ",");
-						}
-						else if (propType == rttr::type::get<std::vector<v3::datetime>>()) {
-							auto vecValue = propValue.get_value<std::vector<v3::datetime>>();
-							result[propName] = v3::utils::join(vecValue, ",");
-						}
-					}
-					return result;
-				}
-				/**
-				 * @brief
-				 * @param obj
-				 * @param values
-				 */
-				static void set_object_value(rttr::instance obj, std::map<std::string, std::string>const& values) {
-					rttr::instance obj1 = obj.get_type().get_raw_type().is_wrapper() ? obj.get_wrapped_instance() : obj;
-					const auto propertys = obj1.get_derived_type().get_properties();
-					for (auto& property : propertys) {
-						auto name = std::string(property.get_name());
-						auto type = property.get_type();
-						if (!values.contains(name))
-							continue;
-						std::string value = values.find(name)->second;
-						if (type == rttr::type::get<int>()) {
-							property.set_value(obj1, atoi(value.c_str()));
-						}
-						else if (type == rttr::type::get<std::int64_t>()) {
-							property.set_value(obj, std::int64_t(std::atoll(value.c_str())));
-						}
-						else if (type == rttr::type::get<float>()) {
-							property.set_value(obj, float(std::atof(value.c_str())));
-						}
-						else if (type == rttr::type::get<double>()) {
-							property.set_value(obj, double(std::atof(value.c_str())));
-						}
-						else if (type == rttr::type::get<long>()) {
-							property.set_value(obj, long(std::atol(value.c_str())));
-						}
-						else if (type == rttr::type::get<bool>()) {
-							if (value == "1" || value == "true" || value == "TRUE" || value == "True") {
-								property.set_value(obj, true);
-							}
-							else {
-								property.set_value(obj, false);
-							}
-						}
-						else if (type == rttr::type::get<std::string>()) {
-							property.set_value(obj, value);
-						}
-						else if (type == rttr::type::get<v3::datetime>()) {
-							property.set_value(obj, v3::datetime(value));
-						}
-						else if (type == rttr::type::get<std::vector<int>>()) {
-							std::vector<std::string> vec = v3::utils::split(value, ",");
-							std::vector<int> vecValue;
-							for (auto vecIt : vec) {
-								vecValue.push_back(std::atoi(vecIt.c_str()));
-							}
-							property.set_value(obj, vecValue);
-						}
-						else if (type == rttr::type::get<std::vector<std::int64_t>>()) {
-							std::vector<std::string> vec = v3::utils::split(value, ",");
-							std::vector<std::int64_t> vecValue;
-							for (auto vecIt : vec) {
-								vecValue.push_back(std::atoll(vecIt.c_str()));
-							}
-							property.set_value(obj, vecValue);
-						}
-						else if (type == rttr::type::get<std::vector<float>>()) {
-							std::vector<std::string> vec = v3::utils::split(value, ",");
-							std::vector<float> vecValue;
-							for (auto vecIt : vec) {
-								vecValue.push_back(std::atof(vecIt.c_str()));
-							}
-							property.set_value(obj, vecValue);
-						}
-						else if (type == rttr::type::get<std::vector<double>>()) {
-							std::vector<std::string> vec = v3::utils::split(value, ",");
-							std::vector<double> vecValue;
-							for (auto vecIt : vec) {
-								vecValue.push_back(std::atof(vecIt.c_str()));
-							}
-							property.set_value(obj, vecValue);
-						}
-						else if (type == rttr::type::get<std::vector<long>>()) {
-							std::vector<std::string> vec = v3::utils::split(value, ",");
-							std::vector<long> vecValue;
-							for (auto vecIt : vec) {
-								vecValue.push_back(std::atol(vecIt.c_str()));
-							}
-							property.set_value(obj, vecValue);
-						}
-						else if (type == rttr::type::get<std::vector<bool>>()) {
-							std::vector<std::string> vec = v3::utils::split(value, ",");
-							std::vector<bool> vecValue;
-							for (auto vecIt : vec) {
-								vecValue.push_back(vecIt == "1" || vecIt == "true" || vecIt == "TRUE" || vecIt == "True");
-							}
-							property.set_value(obj, vecValue);
-						}
-						else if (type == rttr::type::get<std::vector<std::string>>()) {
-							std::vector<std::string> vecValue = v3::utils::split(value, ",");
-							property.set_value(obj, vecValue);
-						}
-						else if (type == rttr::type::get<std::vector<v3::datetime>>()) {
-							std::vector<std::string> vec = v3::utils::split(value, ",");
-							std::vector<v3::datetime> vecValue;
-							for (auto vecIt : vec) {
-								vecValue.push_back(v3::datetime(vecIt));
-							}
-							property.set_value(obj, vecValue);
-						}
-					}
-				}
-			};
-
-			class cookie_id {
-			public:
-				static std::string get_id() {
-					static std::string g_cookie_id;
-					if (g_cookie_id.empty()) {
-						g_cookie_id = v3::utils::uuid();
-					}
-					return g_cookie_id;
-				}
-			};
-
-			class cookie {
-			public:
-				cookie() {
-					//name = "SessionId";
-					name = cookie_id::get_id();
-					value = v3::utils::base64_encode(v3::utils::uuid());
-					path = "path=/";
-					time = 30 * 60 * 1000;
-					last_expire_time = v3::datetime::current_time_stamp() + time;
-				}
-				/**
-				 * @brief cookie名称
-				 */
-				std::string name;
-				/**
-				 * @brief cookie值
-				 */
-				std::string value;
-				/**
-				 * @brief cookie路径
-				 */
-				std::string path;
-				/**
-				 * @brief cookie时间
-				 */
-				time_t		time = 0;
-				/**
-				 * @brief 上次刷新时间
-				 */
-				time_t last_expire_time = 0;
-				/**
-				 * @brief 对比
-				 * @param cookie
-				 * @param remove
-				 * @return
-				 */
-				bool compare(std::shared_ptr<cookie> cookie, bool& remove) {
-					bool result = false;
-					remove = false;
-					if (cookie) {
-						result = (name == cookie->name && value == cookie->value);
-						if (result) {
-							time_t current_time = v3::datetime::current_time_stamp();
-							if (last_expire_time < current_time) {
-								remove = true;
-								result = false;
-							}
-							else {
-								last_expire_time = v3::datetime::current_time_stamp() + time;
-							}
-						}
-					}
-					return result;
-				}
-			};
-
-			class cookies {
-			public:
-				/**
-				 * @brief 解析
-				 * @param cookie_str
-				 * @return
-				 */
-				static std::shared_ptr<cookies> analysis(std::string const& cookie_str) {
-					std::shared_ptr<cookies> result;
-					std::vector<std::string> cookies_tmp = v3::utils::split(cookie_str, ";");
-					for (auto& item : cookies_tmp) {
-						int index = item.find('=');
-						if (index == std::string::npos)
-							continue;
-						std::shared_ptr<cookie> add(new cookie);
-						add->name = item.substr(0, index);
-						add->value = item.substr(index + 1);
-						add->name = v3::utils::trim(add->name);
-						add->value = v3::utils::trim(add->value);
-						if (add->name != "path") {
-							if (!result) {
-								result.reset(new cookies);
-							}
-							result->cookies_.push_back(add);
-						}
-					}
-					return result;
-				}
-				/**
-				 * @brief 对比
-				 * @param value
-				 * @return
-				 */
-				bool compare(std::shared_ptr<cookies> value) {
-					bool result = false;
-					if (!value)
-						return result;
-					for (auto& value_elem : value->cookies_) {
-						for (int i = 0; i < cookies_.size(); ++i) {
-							bool is_remove = false;
-							bool exist = cookies_[i]->compare(value_elem, is_remove);
-							if (is_remove) {
-								cookies_.erase(cookies_.begin() + i);
-								--i;
-								continue;
-							}
-							if (exist) {
-								result = true;
-							}
-						}
-					}
-					return result;
-				}
-				/**
-				 * @brief 数量
-				 * @return
-				 */
-				int count() {
-					return int(cookies_.size());
-				}
-				/**
-				 * @brief 添加
-				 * @param cookie
-				 */
-				void add(std::shared_ptr<cookie> cookie) {
-					cookies_.push_back(cookie);
-				}
-			private:
-				std::vector<std::shared_ptr<cookie>>	cookies_;
-			};
-
-			struct session {
-				/**
-				 * @brief 关闭
-				 */
-				bool							close = false;
-				/**
-				 * @brief
-				 */
-				bool							authen = false;
-				/**
-				 * @brief
-				 */
-				std::shared_ptr<cookies>		cookies_;
-				/**
-				 * @brief
-				 */
-				std::map<std::string, std::any>	user_data;
-			};
-
-			class sessions {
-			public:
-				/**
-				 * @brief
-				 */
-				static void add_session(std::shared_ptr<session> session) {
-					std::lock_guard<std::mutex> locker(mutex_());
-					sessions_().push_back(session);
-				}
-				/**
-				 * @brief
-				 */
-				static std::shared_ptr<session> get_session(std::string const& cookie_str) {
-					std::shared_ptr<session> result;
-					std::shared_ptr<cookies> cookies = cookies::analysis(cookie_str);
-					{
-						std::lock_guard<std::mutex> locker(mutex_());
-						for (int i = 0; i < sessions_().size(); ++i) {
-							if (sessions_()[i]->cookies_->compare(cookies) && !sessions_()[i]->close) {
-								result = sessions_()[i];
-							}
-							else if (sessions_()[i]->cookies_->count() <= 0 || sessions_()[i]->close) {
-								sessions_().erase(sessions_().begin() + i);
-								i--;
-							}
-						}
-					}
-					return result;
-				}
-			private:
-				static std::vector<std::shared_ptr<session>>& sessions_() {
-					static std::vector<std::shared_ptr<session>> g_sessions;
-					return g_sessions;
-				}
-				static std::mutex& mutex_() {
-					static std::mutex g_mutex;
-					return g_mutex;
-				}
-			};
-
-			enum class captcha_type {
-				/**
-				 * @brief 成功
-				 */
-				success,
-				/**
-				 * @brief 失败
-				 */
-				fail,
-				/**
-				 * @brief 没有验证码
-				 */
-				no
-			};
-
-			struct controller_action;
-
-			class http_context {
-			public:
-				class curr {
-				public:
-					/**
-					 * @brief 当前context
-					 * @return
-					 */
-					static std::shared_ptr<http_context> current() {
-						return http_context::current();
-					}
-					/**
-					 * @brief 是否有权限
-					 * @return
-					 */
-					static bool authen() {
-						return current()->authen();
-					}
-					/**
-					 * @brief 设置权限
-					 * @param value
-					 */
-					static void set_authen(bool value = true) {
-						current()->set_authen(value);
-					}
-					/**
-					 * @brief 设置session
-					 * @param key
-					 * @param value
-					 */
-					static void add_session(std::string const& key, std::any const& value) {
-						current()->add_session(key, value);
-					}
-					/**
-					 * @brief 添加session并设置权限
-					 * @param key
-					 * @param value
-					 */
-					static void add_authen_session(std::string const& key, std::any const& value) {
-						add_session(key, value);
-						set_authen();
-					}
-					/**
-					 * @brief 获取session
-					 * @param key
-					 * @return
-					 */
-					static std::any& session(std::string const& key) {
-						return current()->session(key);
-					}
-					/**
-					 * @brief 获取session
-					 * @tparam _Ret
-					 * @param key
-					 * @param succ
-					 * @return
-					 */
-					template<typename _Ret>
-					static bool get_session(std::string const& key, _Ret& result) {
-						std::any any_value = current()->session(key);
-						if (any_value.type() != typeid(_Ret)) {
-							return false;
-						}
-						result = std::any_cast<_Ret>(any_value);
-						return true;
-					}
-					/**
-					 * @brief 添加cookie
-					 * @param timeout
-					 */
-					static void add_cookie(int timeout = 30) {
-						current()->add_cookie(timeout);
-					}
-					/**
-					 * @brief 删除cookie
-					 */
-					static void remove_cookie() {
-						current()->remove_cookie();
-					}
-					/**
-					 * @brief 重置cookie
-					 * @param timeout
-					 */
-					static void reset_cookie(int timeout = 30) {
-						remove_cookie();
-						add_cookie(timeout);
-					}
-					/**
-					 * @brief 验证码比较
-					 * @param key
-					 * @param captcha_code
-					 * @return
-					 */
-					static captcha_type captcha_compare(std::string const& key, std::string const& captcha_code) {
-						std::string value;
-						if (!get_session<std::string>(key, value))
-							return mvc::captcha_type::no;
-						else if (v3::utils::case_insensitive_compare(value, captcha_code))
-							return mvc::captcha_type::success;
-						else
-							return mvc::captcha_type::fail;
-					}
-					/**
-					 * @brief 验证码比较
-					 * @param key
-					 * @param captcha_code
-					 * @param success
-					 * @param message
-					 * @return
-					 */
-					static bool captcha_compare(std::string const& key, std::string const& captcha_code, bool& success, std::string& message) {
-						auto result = captcha_compare(key, captcha_code);
-						if (mvc::captcha_type::no == result) {
-							success = false;
-							message = "验证码不存在!";
-							return false;
-						}
-						else if (mvc::captcha_type::fail == result) {
-							success = false;
-							message = "验证码错误!";
-							return false;
-						}
-						else {
-							success = true;
-							message = "成功!";
-							return true;
-						}
-					}
-				};
-				/**
-				 * @brief
-				 */
-				static void new_curr_http_context(http::web_request& req, http::web_response& rep) {
-					rep.clear();
-					new http_context(req, rep);
-				}
-				/**
-				 * @brief
-				 */
-				static void remove_curr_http_context() {
-					std::lock_guard<std::mutex> locker(mutex_());
-					http_context_list_().erase(std::this_thread::get_id());
-				}
-				/**
-				 * @brief
-				 * @param route
-				 * @return
-				 */
-				static std::shared_ptr<http_context> current() {
-					std::lock_guard<std::mutex> locker(mutex_());
-					return http_context_list_()[std::this_thread::get_id()];
-				}
-				/**
-				 * @brief
-				 */
-				bool authen() {
-					if (current_session_)
-						return current_session_->authen;
-					return false;
-				}
-				/**
-				 * @brief
-				 */
-				void set_authen(bool value = true) {
-					if (current_session_)
-						current_session_->authen = value;
-				}
-				/**
-				 * @brief
-				 */
-				void add_session(std::string const& key, std::any const& value) {
-					if (!current_session_)
-						throw std::runtime_error("not cookie!");
-					current_session_->user_data[key] = value;
-				}
-				/**
-				 * @brief
-				 */
-				std::any& session(std::string const& key) {
-					static std::any g_any;
-					if (current_session_) {
-						if (current_session_->user_data.find(key) != current_session_->user_data.end()) {
-							return current_session_->user_data[key];
-						}
-					}
-					g_any = std::any();
-					return g_any;
-				}
-				/**
-				 * @brief
-				 */
-				void add_cookie(int timeout = 30) {
-					std::shared_ptr<cookie> item(new cookie);
-					item->time = timeout * (1000 * 60);
-					item->last_expire_time = v3::datetime::current_time_stamp() + item->time;
-					if (current_session_ && !current_session_->close) {
-						if (!current_session_->cookies_)
-							current_session_->cookies_.reset(new cookies);
-						current_session_->cookies_->add(item);
-					}
-					else {
-						current_session_.reset(new mvc::session);
-						current_session_->cookies_.reset(new cookies);
-						current_session_->cookies_->add(item);
-						mvc::sessions::add_session(current_session_);
-					}
-					std::string set_cookie_str;
-					set_cookie_str += item->name;
-					set_cookie_str += "=";
-					set_cookie_str += item->value;
-					set_cookie_str += ";";
-					set_cookie_str += item->path;
-					response.set(http::field::set_cookie, set_cookie_str);
-				}
-				/**
-				 * @brief
-				 */
-				void remove_cookie() {
-					if (current_session_) {
-						current_session_->close = true;
-					}
-					response.set(http::field::set_cookie, "SessionId=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT");
-				}
-				/**
-				 * @brief
-				 */
-				void set_controller_action(std::shared_ptr<controller_action> value) {
-					controller_action_ = value;
-				}
-				/**
-				 * @brief
-				 */
-				std::shared_ptr<controller_action> get_controller_action() {
-					return controller_action_;
-				}
-				/**
-				 * @brief
-				 */
-				http::web_request& request;
-				/**
-				 * @brief
-				 */
-				http::web_response& response;
-				/**
-				 * @brief
-				 */
-				std::filesystem::path root_directory;
-			private:
-				http_context(http::web_request& req, http::web_response& rep) :
-					request(req),
-					response(rep),
-					root_directory(rep.get_root_directory()) {
-					if (req.find(http::field::cookie) != req.end()) {
-						current_session_ = sessions::get_session(std::string(req.find(http::field::cookie)->value().begin(), req.find(http::field::cookie)->value().end()));
-					}
-					std::lock_guard<std::mutex> locker(mutex_());
-					http_context_list_()[std::this_thread::get_id()].reset(this);
-				}
-			private:
-				std::shared_ptr<mvc::session> current_session_;
-				std::shared_ptr<controller_action> controller_action_;
-			private:
-				static std::mutex& mutex_() {
-					static std::mutex g_mutex;
-					return g_mutex;
-				}
-				static std::map<std::thread::id, std::shared_ptr<http_context>>& http_context_list_() {
-					static std::map<std::thread::id, std::shared_ptr<http_context>> g_http_context_list;
-					return g_http_context_list;
-				}
-			};
-
-			class http_context_gc {
-			public:
-				http_context_gc(http::web_request& req, http::web_response& rep) {
-					http_context::new_curr_http_context(req, rep);
-				}
-				virtual ~http_context_gc() {
-					http_context::remove_curr_http_context();
-				}
-			};
-
-			enum class pseudo_type {
-				NON = 0,
-				MASK,
-				MODEL,
-				FOR,
-				IF,
-				SWITCH,
-				FILE
-			};
-
-			struct class_value {
-				bool is_list = false;
-				std::string class_name;
-				std::vector<std::map<std::string, std::string>> class_value;
-			};
-
-			struct ipseudo_label {
-				ipseudo_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
-					type(value_type.first),
-					label(value_type.second) {
-				}
-				/**
-				 * @brief 类型
-				 */
-				pseudo_type										type;
-				/**
-				 * @brief 原始代码
-				 */
-				std::string										html_code;
-				/**
-				 * @brief 临时原始代码
-				 */
-				std::string										html_code_tmp;
-				/**
-				 * @brief 类名
-				 */
-				std::string										class_name;
-				/**
-				 * @brief 标签
-				 */
-				std::pair<std::string, std::string>				label;
-				/**
-				 * @brief 实体类数据列表
-				 */
-				std::vector<std::map<std::string, std::string>> class_value_list;
-				/**
-				 * @brief 子标签
-				 */
-				std::vector<std::shared_ptr<ipseudo_label>>		childs;
-				/**
-				 * @brief 解析返回html
-				 */
-				virtual std::string analysis() = 0;
-				/**
-				 * @brief 设置属性值
-				 */
-				void set_class_value(std::vector<std::shared_ptr<class_value>>const& value) {
-					for (auto it : childs) {
-						it->set_class_value(value);
-					}
-					for (auto it : value) {
-						if (class_name != it->class_name)
-							continue;
-						if (it->is_list && type == pseudo_type::FOR) {
-							class_value_list = it->class_value;
-							break;
-						}
-						else if (!it->is_list) {
-							class_value_list = it->class_value;
-							break;
-						}
-					}
-				}
-				/**
-				 * @brief 解析基础信息
-				 */
-				virtual void analysis_baseinfo() = 0;
-			protected:
-				std::string extract(std::string const& value, std::pair<std::string, std::string> const& pair, int& index) {
-					std::string result;
-					bool ok = false;
-					int count = 0;
-					for (size_t i = 0; i < value.size(); ++i) {
-						if (i + 1 >= pair.first.size() &&
-							value[i] == pair.first[pair.first.size() - 1] &&
-							value.substr(i - pair.first.size() + 1, pair.first.size()) == pair.first) {
-							count++;
-							if (count == 1) {
-								ok = true;
-								continue;
-							}
-						}
-						if (ok &&
-							value.size() >= i + pair.second.size() &&
-							value[i] == pair.second[0] &&
-							value.substr(i, pair.second.size()) == pair.second) {
-							count--;
-							if (count == 0) {
-								index = i + 1;
-								return result;
-							}
-						}
-						if (ok) {
-							result += value[i];
-						}
-					}
-					index = -1;
-					return result;
-				}
-				std::vector<std::string> extractList(std::string const& value, std::pair<std::string, std::string> const& pair) {
-					std::vector<std::string> result;
-					int index = 0;
-					int pos = 0;
-					while (index > -1) {
-						pos += index;
-						std::string ret = extract(value.substr(pos, value.size() - pos), pair, index);
-						if (index != -1)
-							result.push_back(ret);
-					}
-					return result;
-				}
-			};
-
-			struct pseudo_mask_label : public ipseudo_label {
-				pseudo_mask_label(std::pair<pseudo_type, std::pair<std::string, std::string>>const& value_type) :
-					ipseudo_label(value_type) {
-				}
-				std::string mask_name;
-				virtual std::string analysis()override {
-					for (auto child : childs) {
-						std::string childValue = child->analysis();
-						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
-					}
-					int index = 0;
-					std::string header = extract(html_code_tmp, { "${mask","}" }, index);
-					header = "${mask" + header + "}";
-					std::string tmp = extract(html_code_tmp, { header,"{/mask}" }, index);
-					return tmp;
-				}
-				virtual void analysis_baseinfo() override {
-					html_code_tmp = html_code;
-					for (auto child : childs) {
-						child->analysis_baseinfo();
-					}
-					//获取mask名称
-					int index = 0;
-					mask_name = extract(html_code, { "name='","'" }, index);
-				}
-			};
-
-			struct pseudo_model_label : public ipseudo_label {
-				pseudo_model_label(std::pair<pseudo_type, std::pair<std::string, std::string>>const& value_type) :
-					ipseudo_label(value_type) {
-				}
-				virtual std::string analysis()override {
-					for (auto child : childs) {
-						std::string childValue = child->analysis();
-						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
-					}
-					std::string propName;
-					std::string propValue;
-					std::map<std::string, std::string> mapPropValue;
-					{
-						int index = 0;
-						std::string tmp = extract(html_code_tmp, { "name='","'" }, index);
-						std::string::size_type pos = tmp.find('.');
-						if (pos != std::string::npos) {
-							propName = tmp.substr(pos + 1, tmp.size() - pos - 1);
-						}
-					}
-					//获取值
-					{
-						int index = 0;
-						std::string tmp = extract(html_code_tmp.substr(index, html_code_tmp.size() - index), { "value='[","]'" }, index);
-						//属性值
-						if (tmp == "#value") {
-							propValue = tmp;
-						}
-						else {
-							auto values = v3::utils::split(tmp, ",");
-							for (auto value : values) {
-								auto valueItem = v3::utils::split(value, ":");
-								if (valueItem.size() == 2) {
-									if (valueItem[0].size() >= 2 && valueItem[1].size() >= 2 &&
-										valueItem[0][0] == '\'' && valueItem[0][valueItem[0].size() - 1] == '\'' &&
-										valueItem[1][0] == '\'' && valueItem[1][valueItem[1].size() - 1] == '\'') {
-										valueItem[0].erase(valueItem[0].begin());
-										valueItem[0].erase(valueItem[0].begin() + valueItem[0].size() - 1);
-										valueItem[1].erase(valueItem[1].begin());
-										valueItem[1].erase(valueItem[1].begin() + valueItem[1].size() - 1);
-										mapPropValue[valueItem[0]] = valueItem[1];
-									}
-								}
-							}
-						}
-					}
-					if (propName.empty()) {
-						return "";
-					}
-					//属性值
-					if (!propValue.empty() && !class_value_list.empty()) {
-						if (class_value_list[0].find(propName) != class_value_list[0].end()) {
-							return class_value_list[0][propName];
-						}
-					}
-					else if (!mapPropValue.empty() && !class_value_list.empty()) {
-						if (class_value_list[0].find(propName) != class_value_list[0].end()) {
-							std::string value = class_value_list[0][propName];
-							//选择值
-							if (mapPropValue.find(value) != mapPropValue.end()) {
-								return mapPropValue[value];
-							}
-							//默认值
-							else if (mapPropValue.find("default") != mapPropValue.end()) {
-								if (mapPropValue["default"] == "#value") {
-									return class_value_list[0][propName];
-								}
-								else {
-									return mapPropValue["default"];
-								}
-							}
-						}
-					}
-					return "";
-				}
-				virtual void analysis_baseinfo() override {
-					html_code_tmp = html_code;
-					for (auto child : childs) {
-						child->analysis_baseinfo();
-					}
-					//获取类名属性名
-					int index = 0;
-					std::string tmp = extract(html_code, { "name='","'" }, index);
-					std::string::size_type pos = tmp.find('.');
-					if (pos != std::string::npos) {
-						class_name = tmp.substr(0, pos);
-					}
-				}
-			};
-
-			struct pseudo_for_label : public ipseudo_label {
-				pseudo_for_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
-					ipseudo_label(value_type) {
-				}
-				virtual std::string analysis()override {
-					for (auto child : childs) {
-						std::string childValue = child->analysis();
-						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
-					}
-					std::string resultValue;
-					std::string itemName;
-					std::string forLabel;
-					std::vector<std::string> forItemLabelList;
-					std::map<std::string, std::map<std::string, std::map<std::string, std::string>>> forItemLabelValueList;
-					//获取ITEM名称
-					{
-						int index = 0;
-						itemName = extract(html_code_tmp, { "item='","'" }, index);
-						if (itemName.empty())
-							return "";
-					}
-
-					//提取for标签值
-					{
-						int index = 0;
-						std::string header = extract(html_code_tmp, { "${for","}" }, index);
-						header = "${for" + header + "}";
-						forLabel = extract(html_code_tmp, { header,"{/for}" }, index);
-					}
-
-					//提取foritem标签
-					{
-						forItemLabelList = extractList(forLabel, { "{item","/}" });
-						for (auto& it : forItemLabelList) {
-							it = "{item" + it + "/}";
-						}
-						if (forItemLabelList.empty())
-							return forLabel;
-					}
-
-					//提取foritem参数
-					{
-						int index = 0;
-						std::string header = "name='" + itemName + ".";
-						for (auto it : forItemLabelList) {
-							std::string propName = extract(it, { header,"'" }, index);
-							if (propName.empty())
-								continue;
-							std::string value = extract(it, { "value='[","]'" }, index);
-							if (value.empty())
-								continue;
-							if (value == "#value") {
-								forItemLabelValueList[it][propName][value] = value;
-							}
-							else {
-								auto values = v3::utils::split(value, ",");
-								for (auto valueIt : values) {
-									auto valueItem = v3::utils::split(valueIt, "':'");
-									if (valueItem.size() == 2) {
-										valueItem[0] += "'";
-										valueItem[1] = "'" + valueItem[1];
-										if (valueItem[0].size() >= 2 && valueItem[1].size() >= 2 &&
-											valueItem[0][0] == '\'' && valueItem[0][valueItem[0].size() - 1] == '\'' &&
-											valueItem[1][0] == '\'' && valueItem[1][valueItem[1].size() - 1] == '\'') {
-
-											valueItem[0].erase(valueItem[0].begin());
-											valueItem[0].erase(valueItem[0].begin() + valueItem[0].size() - 1);
-
-											valueItem[1].erase(valueItem[1].begin());
-											valueItem[1].erase(valueItem[1].begin() + valueItem[1].size() - 1);
-
-											forItemLabelValueList[it][propName][valueItem[0]] = valueItem[1];
-										}
-									}
-								}
-							}
-						}
-					}
-
-					//遍历值
-					{
-						int index = 0;
-						for (auto item : class_value_list) {
-							index++;
-							std::string itemValue = forLabel;
-							for (auto forItem : forItemLabelList) {
-								//没有查找到值赋值为空
-								if (forItemLabelValueList.find(forItem) == forItemLabelValueList.end()) {
-									itemValue = v3::utils::replace(itemValue, forItem, "");
-									continue;
-								}
-								//查找属性
-								if (forItemLabelValueList[forItem].find("for-index") != forItemLabelValueList[forItem].end()) {
-
-									//默认值
-									if (forItemLabelValueList[forItem]["for-index"].find("#value") != forItemLabelValueList[forItem]["for-index"].end()) {
-
-										itemValue = v3::utils::replace(itemValue, forItem, std::to_string(index));
-									}
-									else {
-										if (forItemLabelValueList[forItem]["for-index"].find(std::to_string(index)) != forItemLabelValueList[forItem]["for-index"].end()) {
-
-											itemValue = v3::utils::replace(itemValue, forItem, forItemLabelValueList[forItem]["for-index"][std::to_string(index)]);
-										}
-										else if (forItemLabelValueList[forItem]["for-index"].find("default") != forItemLabelValueList[forItem]["for-index"].end()) {
-											itemValue = v3::utils::replace(itemValue, forItem, forItemLabelValueList[forItem]["for-index"]["default"]);
-										}
-										else {
-											itemValue = v3::utils::replace(itemValue, forItem, "");
-										}
-									}
-									continue;
-								}
-								else {
-									std::string propNameItem;
-									std::map<std::string, std::string> propValueItem;
-									auto childItem = forItemLabelValueList[forItem];
-									for (auto childItemIt : childItem) {
-										propNameItem = childItemIt.first;
-										propValueItem = childItemIt.second;
-									}
-									if (propNameItem.empty()) {
-										itemValue = v3::utils::replace(itemValue, forItem, "");
-										continue;
-									}
-									if (item.find(propNameItem) != item.end()) {
-										if (item.find(propNameItem) != item.end()) {
-											if (propValueItem.find("#value") != propValueItem.end()) {
-												itemValue = v3::utils::replace(itemValue, forItem, item[propNameItem]);
-											}
-											else if (propValueItem.find(item[propNameItem]) != propValueItem.end()) {
-												itemValue = v3::utils::replace(itemValue, forItem, propValueItem[item[propNameItem]]);
-											}
-											else if (propValueItem.find("default") != propValueItem.end()) {
-
-												if (propValueItem["default"] == "#value") {
-													itemValue = v3::utils::replace(itemValue, forItem, item[propNameItem]);
-												}
-												else {
-													itemValue = v3::utils::replace(itemValue, forItem, propValueItem["default"]);
-												}
-											}
-											else {
-												itemValue = v3::utils::replace(itemValue, forItem, "");
-											}
-										}
-										else {
-											itemValue = v3::utils::replace(itemValue, forItem, "");
-										}
-									}
-									else {
-										itemValue = v3::utils::replace(itemValue, forItem, "");
-									}
-								}
-							}
-							resultValue += itemValue;
-						}
-					}
-					return resultValue;
-				}
-				virtual void analysis_baseinfo() override {
-					html_code_tmp = html_code;
-					for (auto child : childs) {
-						child->analysis_baseinfo();
-					}
-					//获取类名属性名
-					int index = 0;
-					class_name = extract(html_code, { "list='","'" }, index);
-				}
-			};
-
-			struct pseudo_if_label : public ipseudo_label {
-				pseudo_if_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
-					ipseudo_label(value_type) {
-				}
-				virtual std::string analysis()override {
-					for (auto child : childs) {
-						std::string childValue = child->analysis();
-						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
-					}
-					std::string propName;
-					std::string propValue;
-					std::string symbol;
-					std::vector<std::string> labelValue;
-					//提取标签内容
-					{
-						labelValue = extractList(html_code_tmp, { "}","{" });
-						if (labelValue.empty())
-							return "";
-					}
-					//判断结构体是否有值
-					{
-						if (class_value_list.empty()) {
-							if (labelValue.size() == 2) {
-								return labelValue[1];
-							}
-							return "";
-						}
-					}
-					//获取类名属性名
-					{
-						int index = 0;
-						std::string tmp = extract(html_code_tmp, { "name='","'" }, index);
-						std::string::size_type pos = tmp.find('.');
-						if (pos != std::string::npos) {
-							propName = tmp.substr(pos + 1, tmp.size() - pos - 1);
-						}
-					}
-					//判断类名
-					{
-						if (propName.empty()) {
-							if (labelValue.size() == 2) {
-								return labelValue[1];
-							}
-							return "";
-						}
-					}
-					//判断属性名称是否存在
-					{
-						if (class_value_list[0].find(propName) == class_value_list[0].end()) {
-							if (labelValue.size() == 2) {
-								return labelValue[1];
-							}
-							return "";
-						}
-					}
-					//提取操作符 逻辑对比值
-					{
-						int index = 0;
-						propValue = extract(html_code_tmp, { "value=='","'" }, index);
-						//==
-						if (propValue.empty()) {
-							propValue = extract(html_code_tmp, { "value!='","'" }, index);
-							//!=
-							if (propValue.empty()) {
-								propValue = extract(html_code_tmp, { "value>='","'" }, index);
-								//>=
-								if (propValue.empty()) {
-									propValue = extract(html_code_tmp, { "value<='","'" }, index);
-									//<=
-									if (propValue.empty()) {
-										if (labelValue.size() == 2) {
-											return labelValue[1];
-										}
-										return "";
-									}
-									else
-										symbol = "<=";
-								}
-								else
-									symbol = ">=";
-							}
-							else
-								symbol = "!=";
-						}
-						else
-							symbol = "==";
-					}
-					//判断
-					{
-						if (symbol == "==" && propValue.compare(class_value_list[0][propName]) == 0) {
-							return labelValue[0];
-						}
-						else if (symbol == "!=" && propValue.compare(class_value_list[0][propName]) != 0) {
-							return labelValue[0];
-						}
-						else if (symbol == ">=" && propValue.compare(class_value_list[0][propName]) >= 0) {
-							return labelValue[0];
-						}
-						else if (symbol == "<=" && propValue.compare(class_value_list[0][propName]) <= 0) {
-							return labelValue[0];
-						}
-						else {
-							if (labelValue.size() == 2)
-								return labelValue[1];
-						}
-					}
-					return "";
-				}
-				virtual void analysis_baseinfo() override {
-					html_code_tmp = html_code;
-					for (auto child : childs) {
-						child->analysis_baseinfo();
-					}
-					//获取类名属性名
-					int index = 0;
-					std::string tmp = extract(html_code, { "name='","'" }, index);
-					std::string::size_type pos = tmp.find('.');
-					if (pos != std::string::npos) {
-						class_name = tmp.substr(0, pos);
-					}
-				}
-			};
-
-			struct pseudo_switch_label : public ipseudo_label {
-				pseudo_switch_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
-					ipseudo_label(value_type) {
-				}
-				virtual std::string analysis()override {
-					for (auto child : childs) {
-						std::string childValue = child->analysis();
-						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
-					}
-					std::string propName;
-					std::string labelValueDefault;
-					std::vector<std::string> labelValue;
-
-					//获取类名属性名
-					{
-						int index = 0;
-						std::string tmp = extract(html_code_tmp, { "name='","'" }, index);
-						std::string::size_type pos = tmp.find('.');
-						if (pos != std::string::npos) {
-							propName = tmp.substr(pos + 1, tmp.size() - pos - 1);
-						}
-					}
-
-					//提取标签内容
-					{
-						int index = 0;
-						labelValue = extractList(html_code_tmp, { "{case","/case}" });
-						labelValueDefault = extract(html_code_tmp, { "{default}","{/default}" }, index);
-						if (labelValue.empty() && labelValueDefault.empty()) {
-							return "";
-						}
-						else if (labelValue.empty() && !labelValueDefault.empty()) {
-							if (labelValueDefault.find("#value") != std::string::npos) {
-								if (class_value_list.empty())
-									return "";
-								if (propName.empty())
-									return "";
-								if (class_value_list[0].find(propName) == class_value_list[0].end())
-									return "";
-								return class_value_list[0][propName];
-							}
-							return labelValueDefault;
-						}
-					}
-
-					//判断属性值
-					{
-						if (class_value_list.empty()) {
-							if (labelValueDefault.empty())
-								return "";
-							if (labelValueDefault.find("#value") != std::string::npos)
-								return "";
-							return labelValueDefault;
-						}
-
-						if (propName.empty()) {
-							if (labelValueDefault.empty())
-								return "";
-							if (labelValueDefault.find("#value") != std::string::npos)
-								return "";
-							return labelValueDefault;
-						}
-
-						if (class_value_list[0].find(propName) == class_value_list[0].end()) {
-							if (labelValueDefault.empty())
-								return "";
-							if (labelValueDefault.find("#value") != std::string::npos)
-								return "";
-							return labelValueDefault;
-						}
-					}
-
-					//遍历值
-					{
-						for (auto it : labelValue) {
-							int index = 0;
-							std::string propValue = extract(it, { "value='","'" }, index);
-							if (class_value_list[0][propName] == propValue) {
-								return extract(it, { "}","{" }, index);
-							}
-						}
-					}
-
-					//判断默认值
-					{
-						if (labelValueDefault.empty())
-							return "";
-						if (labelValueDefault.find("#value") != std::string::npos) {
-							return v3::utils::replace(labelValueDefault, "#value", class_value_list[0][propName]);
-						}
-						return labelValueDefault;
-					}
-				}
-				virtual void analysis_baseinfo() override {
-					html_code_tmp = html_code;
-					for (auto child : childs) {
-						child->analysis_baseinfo();
-					}
-					//获取类名属性名
-					int index = 0;
-					std::string tmp = extract(html_code, { "name='","'" }, index);
-					std::string::size_type pos = tmp.find('.');
-					if (pos != std::string::npos) {
-						class_name = tmp.substr(0, pos);
-					}
-				}
-			};
-
-			struct pseudo_file_label : public ipseudo_label {
-				pseudo_file_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
-					ipseudo_label(value_type) {
-				}
-				virtual std::string analysis()override {
-					for (auto child : childs) {
-						std::string childValue = child->analysis();
-						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
-					}
-					int index = 0;
-					std::string path_tmp = extract(html_code_tmp, { "path='","'" }, index);
-					std::filesystem::path path = path_tmp;
-					std::filesystem::path filepath;
-					filepath = http_context::current()->response.get_root_directory();
-					filepath.make_preferred();
-					filepath /= path.make_preferred().relative_path();
-					if (filepath.empty())
-						return "";
-					if (std::filesystem::exists(filepath)) {
-						std::ifstream file(filepath, std::ios::in);
-						if (file.is_open()) {
-							return std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
-						}
-					}
-					return "";
-				}
-				virtual void analysis_baseinfo() override {
-					html_code_tmp = html_code;
-					for (auto child : childs) {
-						child->analysis_baseinfo();
-					}
-				}
-			};
-
-			struct pseudo_extract_class_value {
-				template<typename ..._Args>
-				static std::vector<std::shared_ptr<class_value>> get_class_value(_Args&&...args) {
-					std::vector<std::shared_ptr<class_value>> result;
-					auto tuple = std::forward_as_tuple(std::forward<_Args>(args)...);
-					v3::utils::for_each(tuple, [&](auto& it) {
-						auto value = serialize(it);
-						result.push_back(value); });
-					return result;
-				}
-			private:
-				static std::string get_prop_value(rttr::variant const& value) {
-					std::string result;
-					if (value.get_type() == rttr::type::get<int>()) {
-						result = std::to_string(value.get_value<int>());
-					}
-					else if (value.get_type() == rttr::type::get<std::int64_t>()) {
-						result = std::to_string(value.get_value<std::int64_t>());
-					}
-					else if (value.get_type() == rttr::type::get<float>()) {
-						result = v3::utils::format("{:.2f}", value.get_value<float>());
-					}
-					else if (value.get_type() == rttr::type::get<double>()) {
-						result = v3::utils::format("{:.2f}", value.get_value<double>());
-					}
-					else if (value.get_type() == rttr::type::get<long>()) {
-						result = std::to_string(value.get_value<long>());
-					}
-					else if (value.get_type() == rttr::type::get<bool>()) {
-						if (value.get_value<bool>())
-							result = "true";
-						else
-							result = "false";
-					}
-					else if (value.get_type() == rttr::type::get<std::string>()) {
-						result = value.get_value<std::string>();
-					}
-					else if (value.get_type() == rttr::type::get<v3::datetime>()) {
-						auto t = value.get_value<v3::datetime>();
-						result = t.to_string();
-					}
-					else if (value.get_type() == rttr::type::get<std::vector<int>>()) {
-						auto values = value.get_value<std::vector<int>>();
-						for (int i = 0; i < values.size(); ++i) {
-							if (i + 1 == values.size()) {
-								result += std::to_string(values[i]);
-							}
-							else {
-								result += std::to_string(values[i]) + ",";
-							}
-						}
-					}
-					else if (value.get_type() == rttr::type::get<std::vector<std::int64_t>>()) {
-						auto values = value.get_value<std::vector<std::int64_t>>();
-						for (int i = 0; i < values.size(); ++i) {
-							if (i + 1 == values.size()) {
-								result += std::to_string(values[i]);
-							}
-							else {
-								result += std::to_string(values[i]) + ",";
-							}
-						}
-					}
-					else if (value.get_type() == rttr::type::get<std::vector<float>>()) {
-						auto values = value.get_value<std::vector<float>>();
-						for (int i = 0; i < values.size(); ++i) {
-							if (i + 1 == values.size()) {
-								result += v3::utils::format("{:.2f}", values[i]);
-							}
-							else {
-								result += v3::utils::format("{:.2f}", values[i]) + ",";
-							}
-						}
-					}
-					else if (value.get_type() == rttr::type::get<std::vector<double>>()) {
-						auto values = value.get_value<std::vector<double>>();
-						for (int i = 0; i < values.size(); ++i) {
-							if (i + 1 == values.size()) {
-								result += v3::utils::format("{:.2f}", values[i]);
-							}
-							else {
-								result += v3::utils::format("{:.2f}", values[i]) + ",";
-							}
-						}
-					}
-					else if (value.get_type() == rttr::type::get<std::vector<long>>()) {
-						auto values = value.get_value<std::vector<long>>();
-						for (int i = 0; i < values.size(); ++i) {
-							if (i + 1 == values.size()) {
-								result += std::to_string(values[i]);
-							}
-							else {
-								result += std::to_string(values[i]) + ",";
-							}
-						}
-					}
-					else if (value.get_type() == rttr::type::get<std::vector<bool>>()) {
-						auto values = value.get_value<std::vector<bool>>();
-						for (int i = 0; i < values.size(); ++i) {
-							if (i + 1 == values.size()) {
-								result += values[i] ? "true" : "false";
-							}
-							else {
-								result += values[i] ? "true," : "false,";
-							}
-						}
-					}
-					else if (value.get_type() == rttr::type::get<std::vector<std::string>>()) {
-						auto values = value.get_value<std::vector<std::string>>();
-						for (int i = 0; i < values.size(); ++i) {
-							if (i + 1 == values.size()) {
-								result += values[i];
-							}
-							else {
-								result += values[i] + ",";
-							}
-						}
-					}
-					else if (value.get_type() == rttr::type::get<std::vector<v3::datetime>>()) {
-						auto values = value.get_value<std::vector<v3::datetime>>();
-						for (int i = 0; i < values.size(); ++i) {
-							if (i + 1 == values.size()) {
-								result += values[i].to_string();
-							}
-							else {
-								result += values[i].to_string() + ",";
-							}
-						}
-					}
-					return result;
-				}
-				template<typename _Type>
-				static std::shared_ptr<class_value> serialize(std::vector<std::shared_ptr<_Type>> const& values) {
-					std::vector<_Type> valueTmp;
-					for (auto it : values) {
-						valueTmp.push_back(*it);
-					}
-					return serialize(valueTmp);
-				}
-				template<typename _Type>
-				static std::shared_ptr<class_value> serialize(std::vector<_Type*> values) {
-					std::vector<_Type> valueTmp;
-					for (auto it : values) {
-						valueTmp.push_back(*it);
-					}
-					return serialize(valueTmp);
-				}
-				template<typename _Type>
-				static std::shared_ptr<class_value> serialize(std::vector<_Type> values) {
-					std::shared_ptr<class_value> result(new class_value);
-					rttr::type type = rttr::type::get<_Type>();
-					std::string className(type.get_name());
-					result->class_name = className;
-					result->is_list = true;
-					for (auto it : values) {
-						std::map<std::string, std::string> elem = web_reflect::get_object_value(it);
-						result->class_value.push_back(elem);
-					}
-					return result;
-				}
-				template<typename _Type>
-				static std::shared_ptr<class_value> serialize(std::shared_ptr<_Type> value) {
-					return serialize(*value);
-				}
-				template<typename _Type>
-				static std::shared_ptr<class_value> serialize(_Type* value) {
-					return serialize(*value);
-				}
-				template<typename _Type>
-				static std::shared_ptr<class_value> serialize(_Type value) {
-					std::shared_ptr<class_value> result(new class_value);
-					rttr::type type = rttr::type::get<_Type>();
-					std::string className(type.get_name());
-					result->class_name = className;
-					result->is_list = false;
-					std::map<std::string, std::string> elem = web_reflect::get_object_value(value);
-					result->class_value.push_back(elem);
-					return result;
-				}
-			};
-
-			struct pseudo_extract_label_value {
-				/*
-				* 伪代码结构
-				* 可嵌套 避开关键字 [' }]
-				* ${model name='test_info.userName' value='['${model name='test_info.id' value='[#value]'/}':'启用','false':'禁用'/}
-				*
-				* switch case 中不能存在 #value 属性值  default可以有默认值 可以有固定值
-				* ${switch name='test_info.id'}{case value='1'}<h1>值1</h1>{/case}...{default}<h1>#value</h1>{/default}{/switch}
-				*
-				* if 运算符 == != >= <=
-				* ${if name='test_info.id' value=='100'}<p>判断正确</p>{else}<p>判断错误</p>{/if}
-				*
-				* for for-index 从1开始
-				* ${for item='item' list='test_info'} <td>{item name='item.for-index' value='[#value]'/}</td><td>{item name='item.enable' value='['true':'启用','default':'#value']'/}</td>{/for}
-				*
-				* file path 可以固定 可以嵌套 model设置html路径
-				* ${file path='C:/Users/86158/Desktop/404.html'/}
-				*/
-				static std::vector<std::shared_ptr<ipseudo_label>> analysis(std::string const& html) {
-					std::vector<std::shared_ptr<ipseudo_label>> result;
-					std::pair<std::string, std::string> type = { "${mask","{/mask}" };
-					for (size_t i = 0; i < html.size(); ++i) {
-						if (html.size() > i + type.first.size() &&
-							html[i] == type.first[0] &&
-							html.substr(i, type.first.size()) == type.first) {
-
-							std::string retHtml = nounanalysis(html.substr(i, html.size() - i), result);
-							result[result.size() - 1]->html_code;
-							i += retHtml.size();
-						}
-					}
-					for (auto it : result) {
-						it->analysis_baseinfo();
-					}
-					return result;
-				}
-			private:
-				static std::string nounanalysis(std::string const& html, std::vector<std::shared_ptr<ipseudo_label>>& childs, pseudo_type type = pseudo_type::MASK) {
-					static std::map<pseudo_type, std::pair<std::string, std::string>> g_pseudoLabel = {
-						{
-							pseudo_type::MASK,
-							{"${mask","{/mask}"}
-						},
-						{
-							pseudo_type::MODEL,
-							{"${model","/}"}
-						},
-						{
-							pseudo_type::SWITCH,
-							{"${switch","{/switch}"}
-						},
-						{
-							pseudo_type::IF,
-							{"${if","{/if}"}
-						},
-						{
-							pseudo_type::FOR,
-							{"${for","{/for}"}
-						},
-						{
-							pseudo_type::FILE,
-							{"${file","/}"}
-						}
-					};
-					if (!(html.size() > g_pseudoLabel[type].first.size() &&
-						html.substr(0, g_pseudoLabel[type].first.size()) == g_pseudoLabel[type].first)) {
-						return "";
-					}
-					if (type == pseudo_type::MASK)
-						childs.push_back(std::make_shared<pseudo_mask_label>(*g_pseudoLabel.find(type)));
-					else if (type == pseudo_type::MODEL)
-						childs.push_back(std::make_shared<pseudo_model_label>(*g_pseudoLabel.find(type)));
-					else if (type == pseudo_type::FOR)
-						childs.push_back(std::make_shared<pseudo_for_label>(*g_pseudoLabel.find(type)));
-					else if (type == pseudo_type::IF)
-						childs.push_back(std::make_shared<pseudo_if_label>(*g_pseudoLabel.find(type)));
-					else if (type == pseudo_type::SWITCH)
-						childs.push_back(std::make_shared<pseudo_switch_label>(*g_pseudoLabel.find(type)));
-					else if (type == pseudo_type::FILE)
-						childs.push_back(std::make_shared<pseudo_file_label>(*g_pseudoLabel.find(type)));
-					for (std::string::size_type i = 0; i < html.size(); ++i) {
-						for (auto pseudo : g_pseudoLabel) {
-							if (html.size() > i + pseudo.second.first.size() &&
-								html[i] == pseudo.second.first[0] &&
-								html.substr(i, pseudo.second.first.size()) == pseudo.second.first) {
-								if (i == 0) {
-									break;
-								}
-								else {
-									std::string retHtml = nounanalysis(html.substr(i, html.size() - i), childs[childs.size() - 1]->childs, pseudo.first);
-									childs[childs.size() - 1]->html_code += retHtml;
-									i += retHtml.size();
-								}
-							}
-						}
-						if (type != pseudo_type::NON) {
-							childs[childs.size() - 1]->html_code += html[i];
-						}
-						if (childs[childs.size() - 1]->html_code.size() > g_pseudoLabel[type].second.size() &&
-							childs[childs.size() - 1]->html_code.substr(childs[childs.size() - 1]->html_code.size() - g_pseudoLabel[type].second.size(), g_pseudoLabel[type].second.size()) == g_pseudoLabel[type].second) {
-							return childs[childs.size() - 1]->html_code;
-						}
-					}
-					return "";
-				}
-			};
-
-			enum class from_storage_type {
-				/**
-				 * @brief body
-				*/
-				BODY = 0,
-				/**
-				 * @brief url
-				*/
-				QUERY,
-				/**
-				 * @brief header
-				*/
-				HEADER,
-				/**
-				 * @brief url
-				 */
-				URL
-			};
-
-			enum class argument_type {
-				Json = 0,
-				Multipart,
-				Int,
-				Int64,
-				Float,
-				Double,
-				Long,
-				Bool_,
-				String,
-				DateTime,
-				Binary,
-				VecJson,
-				VecInt,
-				VecInt64,
-				VecFloat,
-				VecDouble,
-				VecLong,
-				VecBool,
-				VecString,
-				VecDateTime
-			};
-
-			enum class http_method {
-				/**
-				 * @brief get
-				*/
-				GET = 0,
-				/**
-				 * @brief post
-				*/
-				POST = 1
-			};
-
-			struct multipart {
-				std::string					content_disposition;
-				std::string					name;
-				std::vector<std::uint8_t>	data;
-				std::string					value;
-				std::string					content_type;
-				std::string					filename;
-				std::string					content_transfer_encoding;
-			};
-
-			struct multipart_value {
-				std::vector<multipart> data;
-				template<typename _Type>
-				_Type value() {
-					_Type result;
-					std::map<std::string, std::string> elem;
-					for (auto value : data) {
-						elem[value.name] = value.value;
-					}
-					web_reflect::set_object_value(result, elem);
-					return result;
-				}
-			};
-
-			struct action_argument {
-				void parameter(http::web_request& request, const rttr::parameter_info& type) {
-					parameter_value_.clear();
-					switch (from_storage_type_) {
-					case from_storage_type::HEADER:  analysis_header(request, type);  return;
-					case from_storage_type::QUERY:   analysis_query(request, type);   return;
-					case from_storage_type::BODY:    analysis_body(request, type);    return;
-					case from_storage_type::URL:     analysis_url(request, type);     return;
-					}
-					throw std::runtime_error("FormStorageType:错误!");
-				}
-				/**
-				 * @brief 参数名称
-				*/
-				std::string					parameter_name_;
-				/**
-				 * @brief 参数
-				*/
-				rttr::variant				parameter_value_;
-				/**
-				 * @brief 数据类型
-				*/
-				argument_type				argument_type_ = argument_type::Binary;
-				/**
-				 * @brief 表单存储类型
-				*/
-				from_storage_type			from_storage_type_ = from_storage_type::QUERY;
-			private:
-				/**
-				 * @brief 解析协议头
-				 * @param request
-				 * @param type
-				*/
-				void analysis_header(http::web_request& request, const rttr::parameter_info& type) {
-					std::map<std::string, std::string> headers;
-					for (auto& it : request) {
-						std::string name(it.name_string().begin(), it.name_string().end());
-						std::string value(it.value().begin(), it.value().end());
-						headers[name] = value;
-					}
-					if (headers.find(parameter_name_) == headers.end())
-						throw std::runtime_error("解析协议头参数错误!");
-					convert(headers[parameter_name_], type);
-				}
-				/**
-				 * @brief 解析url参数
-				 * @param request
-				 * @param type
-				*/
-				void analysis_query(http::web_request& request, const rttr::parameter_info& type) {
-					std::string query(request.query().begin(), request.query().end());
-					std::map<std::string, std::string>  querys = v3::utils::split_http_form(query);
-					if (querys.find(parameter_name_) == querys.end())
-						throw std::runtime_error("解析Query参数错误!");
-					convert(querys[parameter_name_], type);
-				}
-				/**
-				 * @brief 解析BODY
-				 * @param request
-				 * @param type
-				*/
-				void analysis_body(http::web_request& request, const rttr::parameter_info& type) {
-					if (type.get_type() == rttr::type::get<multipart_value>()) {
-						multipart_value parameter;
-						auto multipartValue = request.get_multipart();
-						for (auto it = multipartValue.begin(); it != multipartValue.end(); ++it) {
-							multipart item;
-							item.content_disposition = it->content_disposition();
-							item.name = it->name();
-							auto valueTmp = it->value();
-							item.data.insert(item.data.end(), valueTmp.begin(), valueTmp.end());
-							if (it->filename().empty()) {
-								try {
-									item.value = it->value();
-								}
-								catch (...) {}
-							}
-							item.content_type = it->content_type();
-							item.filename = it->filename();
-							item.content_transfer_encoding = it->content_transfer_encoding();
-							parameter.data.push_back(item);
-						}
-						parameter_value_ = parameter;
-					}
-					else if (parameter_name_.empty()) {
-						convert(std::string(request.body().begin(), request.body().end()), type);
-					}
-					else {
-						std::string body(request.body().begin(), request.body().end());
-						std::map<std::string, std::string> bodys = v3::utils::split_http_form(body);
-						if (bodys.find(parameter_name_) == bodys.end())
-							throw std::runtime_error("解析Body参数错误!");
-						convert(bodys[parameter_name_], type);
-					}
-				}
-				/**
-				 * @brief url
-				 * @param request 
-				 * @param type 
-				 */
-				void analysis_url(http::web_request& request, const rttr::parameter_info& type) {
-					std::string query(request.find("http_route_parameter")->value());
-					std::map<std::string, std::string>  querys = v3::utils::split_http_form(query);
-					if (querys.find(parameter_name_) == querys.end())
-						throw std::runtime_error("解析Query参数错误!");
-					convert(querys[parameter_name_], type);
-				}
-				/**
-				 * @brief 数据转换
-				 * @param data
-				 * @param type
-				*/
-				void convert(std::string_view data, const rttr::parameter_info& type) {
-					try {
-						switch (argument_type_) {
-						case argument_type::Json: {
-							parameter_value_ = type.get_type().create();
-							v3::json_convert::deserialize(std::string(data.begin(), data.end()), parameter_value_);
-							return;
-						}
-						case argument_type::Multipart: {
-							return;
-						}
-						case argument_type::Int: {
-							parameter_value_ = std::atoi(std::string(data.begin(), data.end()).c_str());
-							return;
-						}
-						case argument_type::Int64: {
-							parameter_value_ = std::atoll(std::string(data.begin(), data.end()).c_str());
-							return;
-						}
-						case argument_type::Float: {
-							parameter_value_ = std::atof(std::string(data.begin(), data.end()).c_str());
-							return;
-						}
-						case argument_type::Double: {
-							parameter_value_ = std::atof(std::string(data.begin(), data.end()).c_str());
-							return;
-						}
-						case argument_type::Long: {
-							parameter_value_ = std::atol(std::string(data.begin(), data.end()).c_str());
-							return;
-						}
-						case argument_type::Bool_: {
-							std::string tmpValue(data.begin(), data.end());
-							parameter_value_ = tmpValue == "1" || tmpValue == "true" || tmpValue == "TRUE" || tmpValue == "True";
-							return;
-						}
-						case argument_type::String: {
-							parameter_value_ = std::string(data.begin(), data.end());
-							return;
-						}
-						case argument_type::DateTime: {
-							parameter_value_ = datetime(std::string(data.begin(), data.end()));
-							return;
-						}
-						case argument_type::Binary: {
-							parameter_value_ = std::vector<std::uint8_t>(data.begin(), data.end());
-							return;
-						}
-						case argument_type::VecInt: {
-							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
-							std::vector<int> vecValue;
-							for (auto vecIt : vec) {
-								vecValue.push_back(std::atoi(vecIt.c_str()));
-							}
-							parameter_value_ = vecValue;
-							return;
-						}
-						case argument_type::VecInt64: {
-							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
-							std::vector<std::int64_t> vecValue;
-							for (auto vecIt : vec) {
-								vecValue.push_back(std::atoll(vecIt.c_str()));
-							}
-							parameter_value_ = vecValue;
-							return;
-						}
-						case argument_type::VecFloat: {
-							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
-							std::vector<float> vecValue;
-							for (auto vecIt : vec) {
-								vecValue.push_back(std::atof(vecIt.c_str()));
-							}
-							parameter_value_ = vecValue;
-							return;
-						}
-						case argument_type::VecDouble: {
-							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
-							std::vector<double> vecValue;
-							for (auto vecIt : vec) {
-								vecValue.push_back(std::atof(vecIt.c_str()));
-							}
-							parameter_value_ = vecValue;
-							return;
-						}
-						case argument_type::VecLong: {
-							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
-							std::vector<long> vecValue;
-							for (auto vecIt : vec) {
-								vecValue.push_back(std::atol(vecIt.c_str()));
-							}
-							parameter_value_ = vecValue;
-							return;
-						}
-						case argument_type::VecBool: {
-							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
-							std::vector<bool> vecValue;
-							for (auto vecIt : vec) {
-								vecValue.push_back(vecIt == "1" || vecIt == "true" || vecIt == "TRUE" || vecIt == "True");
-							}
-							parameter_value_ = vecValue;
-							return;
-						}
-						case argument_type::VecString: {
-							std::vector<std::string> vecValue = v3::utils::split(std::string(data.begin(), data.end()), ",");
-							parameter_value_ = vecValue;
-							return;
-						}
-						case argument_type::VecDateTime: {
-							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
-							std::vector<datetime> vecValue;
-							for (auto vecIt : vec) {
-								vecValue.push_back(datetime(vecIt));
-							}
-							parameter_value_ = vecValue;
-							return;
-						}
-						}
-					}
-					catch (...) {
-						throw std::runtime_error("解析参数错误");
-					}
-				}
-			};
-
-			struct controller;
-
-			struct controller_action {
-				/**
-				 * @brief 执行动作
-				 * @param request
-				*/
-				rttr::variant invoke(http::web_request& request, rttr::variant& variant, rttr::type const& controller_type) {
-					auto http_current_ptr = http_context::current();
-					//判断contentType
-					std::string content_type = "application/x-www-form-urlencoded";
-					if (request.find(http::field::content_type) != request.end()) {
-						content_type = std::string(request.find(http::field::content_type)->value().begin(), request.find(http::field::content_type)->value().end());
-					}
-					if (content_type.find(content_type) == std::string::npos) {
-						throw std::runtime_error("Content-Type:错误!");
-					}
-					//判断method
-					if (!((method == http_method::GET && request.method() == http::verb::get) || (method == http_method::POST && request.method() == http::verb::post))) {
-						throw std::runtime_error("Method:错误!");
-					}
-					std::vector<rttr::method> find_method;
-					for (auto& it : controller_type.get_methods()) {
-						if (it.get_name() == action_name && it.get_parameter_infos().size() == arguments.size()) {
-							find_method.push_back(it);
-							break;
-						}
-					}
-					if (find_method.empty())
-						throw std::runtime_error("Action:错误!");
-					std::vector<rttr::argument> parameters;
-					std::vector<rttr::variant> variantParameters;
-					{
-						std::lock_guard<std::mutex> locker(mux);
-						for (auto& it : find_method[0].get_parameter_infos()) {
-							arguments[it.get_index()]->parameter(request, it);
-						}
-						for (auto& it : arguments) {
-							variantParameters.push_back(it->parameter_value_);
-						}
-					}
-					for (auto& it : variantParameters) {
-						parameters.push_back(it);
-					}
-					return controller_type.invoke(action_name, variant, parameters);
-				}
-				/**
-				 * @brief 身份验证
-				*/
-				bool											authen = true;
-				/**
-				 * @brief 未登录跳转
-				*/
-				std::string										authen_jump;
-				/**
-				 * @brief 方法名称
-				*/
-				std::string										action_name;
-				/**
-				 * @brief 方式
-				*/
-				http_method										method = http_method::GET;
-				/**
-				 * @brief 数据类型
-				*/
-				std::string										content_type = "application/x-www-form-urlencoded";
-				/**
-				 * @brief 动作类型
-				*/
-				std::string										action_type;
-				/**
-				 * @brief 文件映射
-				*/
-				std::string										file_mapping;
-				/**
-				 * @brief 参数
-				*/
-				std::vector<std::shared_ptr<action_argument>>	arguments;
-				/**
-				 * @brief 控制器
-				*/
-				std::shared_ptr<controller>						parent;
-			private:
-				/**
-				 * @brief 锁
-				*/
-				std::mutex										mux;
-			};
-
-			struct controller {
-				rttr::variant invoke(http::web_request& request) {
-					std::string key(request.find("http_route_key")->value());
-					if (!actions.contains(key))
-						throw std::runtime_error("Action:不存在!");
-					rttr::type type = rttr::type::get_by_name(controller_name);
-					if (!variant.is_valid())
-						variant = type.create();
-					return actions[key]->invoke(request, variant, type);
-				}
-				/**
-				 * @brief 控制器名称
-				*/
-				std::string controller_name;
-				/**
-				 * @brief 动作列表 路由 动作
-				*/
-				std::map<std::string, std::shared_ptr<controller_action>> actions;
-			private:
-				/**
-				 * @brief 对象
-				*/
-				rttr::variant variant;
-			};
-
-			struct mvc_route {
-				bool contains(http::web_request& req) {
-					std::string key;
-					std::string route(req.find("http_route")->value());
-					if (contains(route, key)) {
-						std::size_t index = key.find('<');
-						std::vector<std::string> params;
-						if (std::string::npos != index) {
-							auto keys = v3::utils::split(key.substr(index), "/");
-							auto values = v3::utils::split(route.substr(index), "/");
-							for (int i = 0; i < keys.size() && i < values.size(); ++i) {
-								params.push_back(keys[i].substr(1, keys[i].size() - 2) + "=" + values[i]);
-							}
-						}
-						req.insert("http_route_key",key);
-						req.insert("http_route_parameter", v3::utils::join(params, "&"));
-						return true;
-					}
-					return false;
-				}
-				bool contains(std::string const&route) {
-					std::string key;
-					return contains(route, key);
-				}
-				void add(std::string const& route, std::shared_ptr<controller> value) {
-					routes_[route] = value;
-				}
-				std::shared_ptr<controller>& operator[](std::string const& route) {
-					std::string key;
-					if (contains(route, key)) {
-						return routes_[key];
-					}
-					throw std::runtime_error("key does not exist");
-				}
-				std::shared_ptr<controller>& operator[](http::web_request& req) {
-					return this->operator[](std::string(req.find("http_route_key")->value()));
-				}
-			private:
-				bool contains(std::string const& route, std::string& result) {
-					if (routes_.contains(route)) {
-						result = route;
-						return true;
-					}
-					else {
-						int slash_count = std::count(route.begin(), route.end(), '/');
-						for (auto& [first, second] : routes_) {
-							std::size_t index = first.find('<');
-							if (std::count(first.begin(), first.end(), '/') == slash_count && index != std::string::npos) {
-								if (first.substr(0, index) == route.substr(0, index)) {
-									result = first;
-									return true;
-								}
-							}
-						}
-						return false;
-					}
-				}
-			private:
-				std::map<std::string, std::shared_ptr<controller>> routes_;
-			};
-
-			struct ico_controller {
-				/**
-				 * @brief 注册
-				*/
-				static void attach(std::shared_ptr<controller> controller) {
-					for (auto& [first, second] : controller->actions) {
-						controllers_.add(first, controller);
-					}
-				}
-				/**
-				 * @brief
-				 * @param url
-				 * @return
-				*/
-				static std::shared_ptr<controller> resolve(http::web_request& req) {
-					if (controllers_.contains(req)) {
-						return controllers_[req];
-					}
-					return nullptr;
-				}
-			private:
-				/**
-				 * @brief
-				*/
-				static mvc_route controllers_;
-			};
-			mvc_route ico_controller::controllers_;
-
-			struct web_base_response {
-				void set_header(std::string_view name, std::string_view value) {
-					auto& response = http_context::current()->response;
-					response.set(name, value);
-				}
-				void set_header(http::field field, std::string_view value) {
-					auto& response = http_context::current()->response;
-					response.set(field, value);
-				}
-				void set_value(std::string_view value) {
-					auto& response = http_context::current()->response;
-					response.body().file().close();
-					response.body().text() = std::move(value);
-					auto const size = response.body().size();
-					response.content_length(size);
-				}
-				void set_value(std::vector<std::uint8_t> const& value) {
-					auto& response = http_context::current()->response;
-					response.body().file().close();
-					response.body().text() = std::string((char*)&value[0], value.size());
-					auto const size = response.body().size();
-					response.content_length(size);
-				}
-				void set_status(http::status status = http::status::ok) {
-					auto& response = http_context::current()->response;
-					response.result(status);
-				}
-				std::filesystem::path get_root_directory() {
-					auto& response = http_context::current()->response;
-					return response.get_root_directory();
-				}
-				http::status get_status() {
-					auto& response = http_context::current()->response;
-					return response.result();
-				}
-				std::string get_value() {
-					auto& response = http_context::current()->response;
-					return response.body().text();
-				}
-				void prepare_payload() {
-					auto& response = http_context::current()->response;
-					response.prepare_payload();
-				}
-				void chunked(bool value) {
-					auto& response = http_context::current()->response;
-					response.chunked(value);
-				}
-				void set_server(std::string_view value = BEAST_VERSION_STRING) {
-					auto& response = http_context::current()->response;
-					response.set(http::field::server, value);
-				}
-				void set_version(int ver = 11) {
-					auto& response = http_context::current()->response;
-					response.version(ver);
-				}
-				void fill_file(std::filesystem::path const& path, http::status status = http::status::ok) {
-					auto& response = http_context::current()->response;
-					if (path.c_str()[0] == '/' || path.c_str()[0] == '\\') {
-						response.fill_file(path, status);
-					}
-					else {
-						response.fill_file("/" + path.string(), status);
-					}
-				}
-				void fill_html(std::string const& html, http::status status = http::status::ok) {
-					auto& response = http_context::current()->response;
-					response.fill_html(html, status);
-				}
-				void fill_json(std::string const& json, http::status status = http::status::ok) {
-					auto& response = http_context::current()->response;
-					response.fill_json(json, status);
-				}
-				void fill_page(std::string const& value, http::status status = http::status::ok) {
-					auto& response = http_context::current()->response;
-					response.fill_page(status, value);
-				}
-				void fill_text(std::string const& text, http::status status = http::status::ok) {
-					auto& response = http_context::current()->response;
-					response.fill_text(text, status);
-				}
-				void fill_jump(std::string const& url) {
-					set_header(http::field::content_type, http::extension_to_mimetype("html"));
-					set_header(http::field::location, url);
-					set_status(http::status::found);
-				}
-				void fill_stream(std::vector<std::uint8_t> const& data, std::string const& extension, http::status status = http::status::ok) {
-					set_header("Content-Type", http::extension_to_mimetype(extension));
-					set_value(data);
-					set_status(status);
-				}
-				void fill_download(std::filesystem::path const& path, http::status status = http::status::ok) {
-					set_header(http::field::content_type, "application/octet-stream");
-					set_header(http::field::content_disposition, v3::utils::format("attachment; filename={}", path.filename().string()));
-				}
-				void fill_download(std::filesystem::path const& path, std::string const& filename, http::status status = http::status::ok) {
-					set_header(http::field::content_type, "application/octet-stream");
-					set_header(http::field::content_disposition, v3::utils::format("attachment; filename={}", filename));
-				}
-				void fill_view(http::status status = http::status::ok) {
-					fill_file(get_filename(), status);
-				}
-				std::filesystem::path get_filename() {
-					return mvc::http_context::current()->get_controller_action()->file_mapping;
-				}
-			};
-
-			struct web_result_response : public web_base_response {};
-
-			struct unknown_response : public web_base_response {
-				unknown_response(std::string const& text) {
-					set_value(text);
-					set_status(http::status::unknown);
-				}
-				virtual ~unknown_response() {
-				}
-				operator web_result_response() {
-					return {};
-				}
-			};
-
-			struct jump_response : public web_base_response {
-				jump_response(std::string const& url) {
-					if (!url.empty()) {
-						if (url[0] != '/')
-							fill_jump("/" + url);
-					}
-					else {
-						fill_jump(url);
-					}
-				}
-				virtual ~jump_response() {
-				}
-				operator web_result_response() {
-					return {};
-				}
-			};
-
-			struct text_response : public web_base_response {
-				text_response(std::string const& text, http::status status = http::status::ok) {
-					fill_text(text, status);
-				}
-				virtual ~text_response() {
-				}
-				operator web_result_response() {
-					return {};
-				}
-			};
-
-			struct html_response : public web_base_response {
-				html_response(std::string const& html, http::status status = http::status::ok) {
-					fill_html(html, status);
-				}
-				virtual ~html_response() {
-				}
-				operator web_result_response() {
-					return {};
-				}
-			};
-
-			struct file_response : public web_base_response {
-				file_response() {
-					fill_file(get_filename());
-				}
-				file_response(http::status status = http::status::ok) {
-					fill_file(get_filename(), status);
-				}
-				file_response(std::filesystem::path const& path, http::status status = http::status::ok) {
-					fill_file(path, status);
-				}
-				virtual ~file_response() {
-				}
-				operator web_result_response() {
-					return {};
-				}
-			};
-
-			struct json_response : public web_base_response {
-				json_response(std::string const& json) {
-					fill_json(json);
-				}
-				json_response(char* json) :
-					json_response(std::string(json)) {
-				}
-				json_response(const char* json) :
-					json_response(std::string(json)) {
-				}
-				template<typename _Type>
-				json_response(_Type const& value) {
-					fill_json(v3::json_convert::serialize(value));
-				}
-				virtual~json_response() {
-				}
-				operator web_result_response() {
-					return {};
-				}
-			};
-
-			struct stream_response : public web_base_response {
-				stream_response(std::vector<std::uint8_t> const& data, std::string const& extension, http::status status = http::status::ok) {
-					fill_stream(data, extension, status);
-				}
-				virtual~stream_response() {
-				}
-				operator web_result_response() {
-					return {};
-				}
-			};
-
-			struct download_response : public web_base_response {
-				download_response(std::filesystem::path const& path, http::status status = http::status::ok) {
-					fill_download(path, status);
-				}
-				download_response(std::filesystem::path const& path, std::string const& filename, http::status status = http::status::ok) {
-					fill_download(path, filename, status);
-				}
-				virtual~download_response() {
-				}
-				operator web_result_response() {
-					return {};
-				}
-			};
-
-			struct view : public web_base_response {
-				virtual ~view() {
-				}
-				view() :
-					web_base_response() {
-					fill_view();
-				}
-				view(std::string const& path) :
-					web_base_response() {
-					fill_file(path);
-				}
-				template<typename ..._Args>
-				view(_Args&& ...args) {
-					std::filesystem::path path = get_filename();
-					std::filesystem::path filepath;
-					filepath = http_context::current()->response.get_root_directory();
-					filepath.make_preferred();
-					filepath /= path.make_preferred().relative_path();
-					std::vector<std::uint8_t> value;
-					std::ifstream file(filepath, std::ios::in | std::ios::binary);
-					if (file.is_open()) {
-						file.seekg(0, std::ios::end);
-						int file_size = file.tellg();
-						file.seekg(0, std::ios::beg);
-						value.resize(file_size);
-						file.read((char*)&value[0], file_size);
-						file.close();
-					}
-					std::string html(value.begin(), value.end());
-					auto label_value_list = pseudo_extract_label_value::analysis(html);
-					if (!label_value_list.empty()) {
-						auto classValueList = pseudo_extract_class_value::get_class_value(std::forward<_Args>(args)...);
-						label_value_list[0]->set_class_value(classValueList);
-						html = label_value_list[0]->analysis();
-						fill_html(html);
-					}
-				}
-				operator web_result_response() {
-					return {};
-				}
-			};
-
-			template<int _Width = 100, int _Height = 38, int _Length = 4, int _Line = 2, int _Spot = 200>
-			struct captcha_response : public v3::mvc::web_base_response {
-				captcha_response(std::string const& session_key = "code") :
-					session_key_(session_key) {
-				}
-				virtual ~captcha_response() {
-				}
-				operator v3::mvc::web_result_response() {
-					//验证码
-					std::string captcha_code = generate_captcha_digits();
-					http_context::current()->add_session(session_key_, captcha_code);
-					std::vector<std::uint8_t> img_vec = generate_captcha_image(captcha_code);
-					return v3::mvc::stream_response(img_vec, "bmp");
-				}
-			private:
-				class CImage : public cimg_library::CImg<unsigned char> {
-				public:
-					CImage(const cimg_library::CImg<unsigned char>& img) :
-						cimg_library::CImg<unsigned char>(img) {}
-					cimg_library::CImg<unsigned char>& save_memory_bmp(std::vector<std::uint8_t>& result) {
-						cimg_library::CImg<ucharT> header(54, 1, 1, 1, 0);
-						unsigned char align_buf[4] = {};
-						const unsigned int
-							align = (4 - (3 * _width) % 4) % 4,
-							buf_size = (3 * _width + align) * height(),
-							file_size = 54 + buf_size;
-						header[0] = 'B'; header[1] = 'M';
-						header[0x02] = file_size & 0xFF;
-						header[0x03] = (file_size >> 8) & 0xFF;
-						header[0x04] = (file_size >> 16) & 0xFF;
-						header[0x05] = (file_size >> 24) & 0xFF;
-						header[0x0A] = 0x36;
-						header[0x0E] = 0x28;
-						header[0x12] = _width & 0xFF;
-						header[0x13] = (_width >> 8) & 0xFF;
-						header[0x14] = (_width >> 16) & 0xFF;
-						header[0x15] = (_width >> 24) & 0xFF;
-						header[0x16] = _height & 0xFF;
-						header[0x17] = (_height >> 8) & 0xFF;
-						header[0x18] = (_height >> 16) & 0xFF;
-						header[0x19] = (_height >> 24) & 0xFF;
-						header[0x1A] = 1;
-						header[0x1B] = 0;
-						header[0x1C] = 24;
-						header[0x1D] = 0;
-						header[0x22] = buf_size & 0xFF;
-						header[0x23] = (buf_size >> 8) & 0xFF;
-						header[0x24] = (buf_size >> 16) & 0xFF;
-						header[0x25] = (buf_size >> 24) & 0xFF;
-						header[0x27] = 0x1;
-						header[0x2B] = 0x1;
-						result.insert(result.end(), reinterpret_cast<std::uint8_t*>(header._data), reinterpret_cast<std::uint8_t*>(header._data) + 64);
-						const unsigned char
-							* ptr_r = data(0, _height - 1, 0, 0),
-							* ptr_g = (_spectrum >= 2) ? data(0, _height - 1, 0, 1) : 0,
-							* ptr_b = (_spectrum >= 3) ? data(0, _height - 1, 0, 2) : 0;
-						switch (_spectrum) {
-						case 1: {
-							cimg_forY(*this, y) {
-								cimg_forX(*this, x) {
-									const unsigned char val = (unsigned char)*(ptr_r++);
-									result.push_back(val); result.push_back(val); result.push_back(val);
-								}
-								result.insert(result.end(), reinterpret_cast<std::uint8_t*>(align_buf), reinterpret_cast<std::uint8_t*>(align_buf) + align);
-								ptr_r -= 2 * _width;
-							}
-						} break;
-						case 2: {
-							cimg_forY(*this, y) {
-								cimg_forX(*this, x) {
-									result.push_back(0);
-									result.push_back((unsigned char)(*(ptr_g++)));
-									result.push_back((unsigned char)(*(ptr_r++)));
-								}
-								result.insert(result.end(), reinterpret_cast<std::uint8_t*>(align_buf), reinterpret_cast<std::uint8_t*>(align_buf) + align);
-								ptr_r -= 2 * _width; ptr_g -= 2 * _width;
-							}
-						} break;
-						default: {
-							cimg_forY(*this, y) {
-								cimg_forX(*this, x) {
-									result.push_back((unsigned char)(*(ptr_b++)));
-									result.push_back((unsigned char)(*(ptr_g++)));
-									result.push_back((unsigned char)(*(ptr_r++)));
-								}
-								result.insert(result.end(), reinterpret_cast<std::uint8_t*>(align_buf), reinterpret_cast<std::uint8_t*>(align_buf) + align);
-								ptr_r -= 2 * _width; ptr_g -= 2 * _width; ptr_b -= 2 * _width;
-							}
-						}
-						}
-						return *this;
-					}
-				};
-			private:
-				//获取验证码
-				std::string generate_captcha_digits() {
-					static const char data_character[] = "23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ\0";
-					int min = 0;
-					int max = std::strlen(data_character) - 1;
-					std::string result;
-					for (int i = 0; i < _Length; ++i) {
-						result += data_character[v3::utils::random(min, max)];
-					}
-					return result;
-				}
-				//生成随机颜色
-				unsigned char* generate_random_color() {
-					static unsigned char colors[][3] = {
-						{47,79,79     },
-						{105,105,105  },
-						{0,0,128      },
-						{100,149,237  },
-						{72,61,139    },
-						{106,90,205   },
-						{123,104,238  },
-						{132,112,255  },
-						{65,105,225   },
-						{85,107,47    },
-						{107,142,35   },
-						{205,92,92    },
-						{160,82,45    },
-						{178,34,34    },
-						{255,69,0     },
-						{176,48,96    },
-						{160,32,240   },
-						{139,137,137  },
-						{0,139,139    },
-						{139,0,0      },
-						{139,0,139    },
-						{154,50,205   },
-						{238,64,0     },
-						{0,139,69     } };
-					return colors[v3::utils::random(0, sizeof(colors) / sizeof(colors[0]) - 1)];
-				}
-				//生成字体大小,位置
-				std::vector<std::tuple<int, int, int>> generate_font_size() {
-					std::vector<std::tuple<int, int, int>> result;
-					int s_width = _Width / _Length;
-					int s_height = _Height;
-					for (int i = 0; i < _Length; ++i) {
-						int x = 0, y = 0, s = 0;
-						double font_centre_pos = 0.0;
-						if (s_width > s_height) {
-							s = v3::utils::random(double(s_height) - double(s_height) * 0.2, double(s_height) * 1.2);
-						}
-						else {
-							s = v3::utils::random(double(s_width) - double(s_width) * 0.2, double(s_width) * 1.2);
-						}
-						font_centre_pos = double(s) * 0.8;
-						x = v3::utils::random(0, double(s_width) - font_centre_pos);
-						y = v3::utils::random(0, double(s_height) - font_centre_pos);
-						result.push_back(std::make_tuple(s, x, y));
-					}
-					return result;
-				}
-				//验证码图片
-				std::vector<std::uint8_t> generate_captcha_image(std::string const& code) {
-					std::vector<std::uint8_t> result;
-					cimg_library::CImg<unsigned char> image(_Width, _Height, 1, 3, 255);  // 创建一个白色背景的图像
-					int s_width = _Width / _Length;
-					int s_height = _Height;
-					std::vector<std::tuple<int, int, int>> font_info = generate_font_size();
-					char c[2] = { 0 };
-					//绘制验证码
-					for (int i = 0; i < _Length; ++i) {
-						c[0] = code[i];
-						image.draw_text(i * s_width + std::get<1>(font_info[i]), std::get<2>(font_info[i]), c, generate_random_color(), 0, 1, std::get<0>(font_info[i])).width();
-					}
-					//绘制干扰线
-					for (int i = 0; i < _Line; ++i) {
-						int x1 = std::rand() % _Width;
-						int y1 = std::rand() % _Height;
-						int x2 = std::rand() % _Width;
-						int y2 = std::rand() % _Height;
-						// 生成随机颜色
-						image.draw_line(x1, y1, x2, y2, generate_random_color());
-					}
-					//绘制干扰点
-					for (int i = 0; i < _Spot; ++i) {
-						int x = std::rand() % _Width;
-						int y = std::rand() % _Height;
-						// 生成随机颜色
-						image.draw_point(x, y, generate_random_color());
-					}
-
-					//扭曲图像
-					cimg_library::CImg<unsigned char> distorted_image(_Width, _Height, 1, 3, 255);
-					cimg_forXY(image, xx, yy) {
-						int new_xx = xx + static_cast<int>(1.32 * sin(2 * 3.14 * yy * 0.045));
-						int new_yy = yy + static_cast<int>(1.42 * sin(2 * 3.14 * xx * 0.062));
-						if (new_xx >= 0 && new_xx < _Width && new_yy >= 0 && new_yy < _Height) {
-							distorted_image(xx, yy, 0, 0) = image(new_xx, new_yy, 0, 0);
-							distorted_image(xx, yy, 0, 1) = image(new_xx, new_yy, 0, 1);
-							distorted_image(xx, yy, 0, 2) = image(new_xx, new_yy, 0, 2);
-						}
-					}
-					CImage(distorted_image).save_memory_bmp(result);
-					return result;
-				}
-			private:
-				std::string session_key_;
-			};
-
-			class http_server_t {
-			public:
-				http_server_t() {
-					server_.bind<http::verb::post, http::verb::get>(std::string("/*"), &http_server_t::on_base_request, this);
-				}
-				bool start(std::string const& ip, int port) {
-					return server_.start(ip, port);
-				}
-				void stop() {
-					server_.stop();
-				}
-				void set_root_directory(std::filesystem::path const& path) {
-					server_.set_root_directory(path);
-				}
-			protected:
-				virtual void on_request(http::web_request& req, http::web_response& rep) = 0;
-			private:
-				void on_base_request(std::shared_ptr<asio2::http_session>& session_ptr, http::web_request& req, http::web_response& rep) {
-					on_request(req, rep);
-				}
-			private:
-				asio2::http_server server_;
-			};
-			class https_server_t {
-			public:
-				https_server_t() {
-					server_.bind<http::verb::post, http::verb::get>("/*", &https_server_t::on_base_request, this);
-				}
-				bool start(std::string const& ip, int port) {
-					return server_.start(ip, port);
-				}
-				void stop() {
-					server_.stop();
-				}
-				void set_root_directory(std::filesystem::path const& path) {
-					server_.set_root_directory(path);
-				}
-				void set_cert_file(std::string const& ca_cert_file, std::string const& private_cert_file, std::string const& private_key_file, std::string const& private_password) {
-					server_.set_cert_file(ca_cert_file, private_cert_file, private_key_file, private_password);
-				}
-			protected:
-				virtual void on_request(http::web_request& req, http::web_response& rep) = 0;
-			private:
-				void on_base_request(std::shared_ptr<asio2::https_session>& session_ptr, http::web_request& req, http::web_response& rep) {
-					on_request(req, rep);
-				}
-			private:
-				asio2::https_server server_;
-			};
-			template<typename _Before, typename _Err, typename _After, typename _TypeBase>
-			class http_server_base : public _TypeBase {
-			public:
-				http_server_base() :
-					_TypeBase() {
-				}
-			private:
-				virtual void on_request(http::web_request& req, http::web_response& rep)override {
-					http_context_gc http_context(req, rep);
-					try {
-						req.insert("http_route",std::string(req.path()).substr(1));
-						std::shared_ptr<controller> controller = v3::mvc::ico_controller::resolve(req);
-						std::string key(req.find("http_route_key")->value());
-						http_context::current()->set_controller_action((bool)controller ? controller->actions[key] : nullptr);
-						if (before_.before((bool)controller ? controller->actions[key] : nullptr, req, rep)) {
-							rttr::variant variant = controller->invoke(req);
-							if (variant.is_valid()) {
-								auto response = variant.get_value<web_base_response>();
-								response.set_version();
-								response.set_server();
-								response.chunked(true);
-								response.prepare_payload();
-							}
-						}
-						//文件
-						else {
-							rep.fill_file(req.path());
-							rep.set(http::field::cache_control, "max-age=31536000");
-							rep.chunked(true);
-						}
-					}
-					catch (unknown_response const&) {
-					}
-					catch (jump_response const&) {
-					}
-					catch (text_response const&) {
-					}
-					catch (html_response const&) {
-					}
-					catch (file_response const&) {
-					}
-					catch (json_response const&) {
-					}
-					catch (std::exception const& ec) {
-						err_.error(ec.what(), req, rep);
-					}
-					catch (...) {
-						err_.error("未知异常", req, rep);
-					}
-					after_.after(req, rep);
-				}
-			private:
-				_Before	before_;
-				_Err	err_;
-				_After	after_;
-			};
-			template<typename _Before, typename _Err, typename _After>
-			using http_server = http_server_base<_Before, _Err, _After, http_server_t>;
-			template<typename _Before, typename _Err, typename _After>
-			using https_server = http_server_base<_Before, _Err, _After, https_server_t>;
-		}
-	}
-}
+#include "mvc_impl.h"

+ 2748 - 0
robot/robotics/mvc_impl.h

@@ -0,0 +1,2748 @@
+#pragma once
+#ifdef WINDOWS_BUILD
+#ifdef MVC_EXPORTS
+#define MVC_API _declspec(dllexport)
+#else
+#define MVC_API _declspec(dllimport)
+#endif
+#elif LINUX_BUILD
+#define MVC_API
+#endif
+//asio2
+#include <asio2/asio2.hpp>
+//robotics
+#include "utils.hpp"
+#include "json.hpp"
+#include "CImg.h"
+
+namespace robotics {
+	namespace v3 {
+		namespace mvc {
+			class web_reflect {
+			public:
+				/**
+				 * @brief
+				 * @param obj
+				 */
+				static std::map<std::string, std::string> get_object_value(rttr::instance obj) {
+					std::map<std::string, std::string> result;
+					auto propertys = obj.get_type().get_properties();
+					for (auto& property : propertys) {
+						std::string propName(property.get_name());
+						rttr::variant propValue = property.get_value(obj);
+						rttr::type propType = property.get_type();
+						if (propType == rttr::type::get<int>()) {
+							result[propName] = std::to_string(propValue.get_value<int>());
+						}
+						else if (propType == rttr::type::get<std::int64_t>()) {
+							result[propName] = std::to_string(propValue.get_value<std::int64_t>());
+						}
+						else if (propType == rttr::type::get<float>()) {
+							result[propName] = v3::utils::format("{:.2f}", propValue.get_value<float>());
+						}
+						else if (propType == rttr::type::get<double>()) {
+							result[propName] = v3::utils::format("{:.2f}", propValue.get_value<double>());
+						}
+						else if (propType == rttr::type::get<long>()) {
+							result[propName] = std::to_string(propValue.get_value<long>());
+						}
+						else if (propType == rttr::type::get<bool>()) {
+							result[propName] = propValue.get_value<bool>() ? "true" : "false";
+						}
+						else if (propType == rttr::type::get<std::string>()) {
+							result[propName] = propValue.get_value<std::string>();
+						}
+						else if (propType == rttr::type::get<v3::datetime>()) {
+							result[propName] = propValue.get_value<v3::datetime>().to_string();
+						}
+						else if (propType == rttr::type::get<std::vector<int>>()) {
+							auto vecValue = propValue.get_value<std::vector<int>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+						else if (propType == rttr::type::get<std::vector<std::int64_t>>()) {
+							auto vecValue = propValue.get_value<std::vector<std::int64_t>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+						else if (propType == rttr::type::get<std::vector<float>>()) {
+							auto vecValue = propValue.get_value<std::vector<float>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+						else if (propType == rttr::type::get<std::vector<double>>()) {
+							auto vecValue = propValue.get_value<std::vector<double>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+						else if (propType == rttr::type::get<std::vector<long>>()) {
+							auto vecValue = propValue.get_value<std::vector<long>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+						else if (propType == rttr::type::get<std::vector<bool>>()) {
+							auto vecValue = propValue.get_value<std::vector<bool>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+						else if (propType == rttr::type::get<std::vector<std::string>>()) {
+							auto vecValue = propValue.get_value<std::vector<std::string>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+						else if (propType == rttr::type::get<std::vector<v3::datetime>>()) {
+							auto vecValue = propValue.get_value<std::vector<v3::datetime>>();
+							result[propName] = v3::utils::join(vecValue, ",");
+						}
+					}
+					return result;
+				}
+				/**
+				 * @brief
+				 * @param obj
+				 * @param values
+				 */
+				static void set_object_value(rttr::instance obj, std::map<std::string, std::string>const& values) {
+					rttr::instance obj1 = obj.get_type().get_raw_type().is_wrapper() ? obj.get_wrapped_instance() : obj;
+					const auto propertys = obj1.get_derived_type().get_properties();
+					for (auto& property : propertys) {
+						auto name = std::string(property.get_name());
+						auto type = property.get_type();
+						if (!values.contains(name))
+							continue;
+						std::string value = values.find(name)->second;
+						if (type == rttr::type::get<int>()) {
+							property.set_value(obj1, atoi(value.c_str()));
+						}
+						else if (type == rttr::type::get<std::int64_t>()) {
+							property.set_value(obj, std::int64_t(std::atoll(value.c_str())));
+						}
+						else if (type == rttr::type::get<float>()) {
+							property.set_value(obj, float(std::atof(value.c_str())));
+						}
+						else if (type == rttr::type::get<double>()) {
+							property.set_value(obj, double(std::atof(value.c_str())));
+						}
+						else if (type == rttr::type::get<long>()) {
+							property.set_value(obj, long(std::atol(value.c_str())));
+						}
+						else if (type == rttr::type::get<bool>()) {
+							if (value == "1" || value == "true" || value == "TRUE" || value == "True") {
+								property.set_value(obj, true);
+							}
+							else {
+								property.set_value(obj, false);
+							}
+						}
+						else if (type == rttr::type::get<std::string>()) {
+							property.set_value(obj, value);
+						}
+						else if (type == rttr::type::get<v3::datetime>()) {
+							property.set_value(obj, v3::datetime(value));
+						}
+						else if (type == rttr::type::get<std::vector<int>>()) {
+							std::vector<std::string> vec = v3::utils::split(value, ",");
+							std::vector<int> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atoi(vecIt.c_str()));
+							}
+							property.set_value(obj, vecValue);
+						}
+						else if (type == rttr::type::get<std::vector<std::int64_t>>()) {
+							std::vector<std::string> vec = v3::utils::split(value, ",");
+							std::vector<std::int64_t> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atoll(vecIt.c_str()));
+							}
+							property.set_value(obj, vecValue);
+						}
+						else if (type == rttr::type::get<std::vector<float>>()) {
+							std::vector<std::string> vec = v3::utils::split(value, ",");
+							std::vector<float> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atof(vecIt.c_str()));
+							}
+							property.set_value(obj, vecValue);
+						}
+						else if (type == rttr::type::get<std::vector<double>>()) {
+							std::vector<std::string> vec = v3::utils::split(value, ",");
+							std::vector<double> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atof(vecIt.c_str()));
+							}
+							property.set_value(obj, vecValue);
+						}
+						else if (type == rttr::type::get<std::vector<long>>()) {
+							std::vector<std::string> vec = v3::utils::split(value, ",");
+							std::vector<long> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atol(vecIt.c_str()));
+							}
+							property.set_value(obj, vecValue);
+						}
+						else if (type == rttr::type::get<std::vector<bool>>()) {
+							std::vector<std::string> vec = v3::utils::split(value, ",");
+							std::vector<bool> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(vecIt == "1" || vecIt == "true" || vecIt == "TRUE" || vecIt == "True");
+							}
+							property.set_value(obj, vecValue);
+						}
+						else if (type == rttr::type::get<std::vector<std::string>>()) {
+							std::vector<std::string> vecValue = v3::utils::split(value, ",");
+							property.set_value(obj, vecValue);
+						}
+						else if (type == rttr::type::get<std::vector<v3::datetime>>()) {
+							std::vector<std::string> vec = v3::utils::split(value, ",");
+							std::vector<v3::datetime> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(v3::datetime(vecIt));
+							}
+							property.set_value(obj, vecValue);
+						}
+					}
+				}
+			};
+
+			class cookie_id {
+			public:
+				static std::string get_id() {
+					static std::string g_cookie_id;
+					if (g_cookie_id.empty()) {
+						g_cookie_id = v3::utils::uuid();
+					}
+					return g_cookie_id;
+				}
+			};
+
+			class cookie {
+			public:
+				cookie() {
+					//name = "SessionId";
+					name = cookie_id::get_id();
+					value = v3::utils::base64_encode(v3::utils::uuid());
+					path = "path=/";
+					time = 30 * 60 * 1000;
+					last_expire_time = v3::datetime::current_time_stamp() + time;
+				}
+				/**
+				 * @brief cookie名称
+				 */
+				std::string name;
+				/**
+				 * @brief cookie值
+				 */
+				std::string value;
+				/**
+				 * @brief cookie路径
+				 */
+				std::string path;
+				/**
+				 * @brief cookie时间
+				 */
+				time_t		time = 0;
+				/**
+				 * @brief 上次刷新时间
+				 */
+				time_t last_expire_time = 0;
+				/**
+				 * @brief 对比
+				 * @param cookie
+				 * @param remove
+				 * @return
+				 */
+				bool compare(std::shared_ptr<cookie> cookie, bool& remove) {
+					bool result = false;
+					remove = false;
+					if (cookie) {
+						result = (name == cookie->name && value == cookie->value);
+						if (result) {
+							time_t current_time = v3::datetime::current_time_stamp();
+							if (last_expire_time < current_time) {
+								remove = true;
+								result = false;
+							}
+							else {
+								last_expire_time = v3::datetime::current_time_stamp() + time;
+							}
+						}
+					}
+					return result;
+				}
+			};
+
+			class cookies {
+			public:
+				/**
+				 * @brief 解析
+				 * @param cookie_str
+				 * @return
+				 */
+				static std::shared_ptr<cookies> analysis(std::string const& cookie_str) {
+					std::shared_ptr<cookies> result;
+					std::vector<std::string> cookies_tmp = v3::utils::split(cookie_str, ";");
+					for (auto& item : cookies_tmp) {
+						int index = item.find('=');
+						if (index == std::string::npos)
+							continue;
+						std::shared_ptr<cookie> add(new cookie);
+						add->name = item.substr(0, index);
+						add->value = item.substr(index + 1);
+						add->name = v3::utils::trim(add->name);
+						add->value = v3::utils::trim(add->value);
+						if (add->name != "path") {
+							if (!result) {
+								result.reset(new cookies);
+							}
+							result->cookies_.push_back(add);
+						}
+					}
+					return result;
+				}
+				/**
+				 * @brief 对比
+				 * @param value
+				 * @return
+				 */
+				bool compare(std::shared_ptr<cookies> value) {
+					bool result = false;
+					if (!value)
+						return result;
+					for (auto& value_elem : value->cookies_) {
+						for (int i = 0; i < cookies_.size(); ++i) {
+							bool is_remove = false;
+							bool exist = cookies_[i]->compare(value_elem, is_remove);
+							if (is_remove) {
+								cookies_.erase(cookies_.begin() + i);
+								--i;
+								continue;
+							}
+							if (exist) {
+								result = true;
+							}
+						}
+					}
+					return result;
+				}
+				/**
+				 * @brief 数量
+				 * @return
+				 */
+				int count() {
+					return int(cookies_.size());
+				}
+				/**
+				 * @brief 添加
+				 * @param cookie
+				 */
+				void add(std::shared_ptr<cookie> cookie) {
+					cookies_.push_back(cookie);
+				}
+			private:
+				std::vector<std::shared_ptr<cookie>>	cookies_;
+			};
+
+			struct session {
+				/**
+				 * @brief 关闭
+				 */
+				bool							close = false;
+				/**
+				 * @brief
+				 */
+				bool							authen = false;
+				/**
+				 * @brief
+				 */
+				std::shared_ptr<cookies>		cookies_;
+				/**
+				 * @brief
+				 */
+				std::map<std::string, std::any>	user_data;
+			};
+
+			class MVC_API sessions {
+			public:
+				/**
+				 * @brief
+				 */
+				static void add_session(std::shared_ptr<session> session) {
+					std::lock_guard<std::mutex> locker(mutex_);
+					sessions_.push_back(session);
+				}
+				/**
+				 * @brief
+				 */
+				static std::shared_ptr<session> get_session(std::string const& cookie_str) {
+					std::shared_ptr<session> result;
+					std::shared_ptr<cookies> cookies = cookies::analysis(cookie_str);
+					{
+						std::lock_guard<std::mutex> locker(mutex_);
+						for (int i = 0; i < sessions_.size(); ++i) {
+							if (sessions_[i]->cookies_->compare(cookies) && !sessions_[i]->close) {
+								result = sessions_[i];
+							}
+							else if (sessions_[i]->cookies_->count() <= 0 || sessions_[i]->close) {
+								sessions_.erase(sessions_.begin() + i);
+								i--;
+							}
+						}
+					}
+					return result;
+				}
+			private:
+				static std::vector<std::shared_ptr<session>> sessions_;
+				static std::mutex							 mutex_;
+			};
+
+			enum class captcha_type {
+				/**
+				 * @brief 成功
+				 */
+				success,
+				/**
+				 * @brief 失败
+				 */
+				fail,
+				/**
+				 * @brief 没有验证码
+				 */
+				no
+			};
+
+			struct controller_action;
+
+			class MVC_API http_context {
+			public:
+				class curr {
+				public:
+					/**
+					 * @brief 当前context
+					 * @return
+					 */
+					static std::shared_ptr<http_context> current() {
+						return http_context::current();
+					}
+					/**
+					 * @brief 是否有权限
+					 * @return
+					 */
+					static bool authen() {
+						return current()->authen();
+					}
+					/**
+					 * @brief 设置权限
+					 * @param value
+					 */
+					static void set_authen(bool value = true) {
+						current()->set_authen(value);
+					}
+					/**
+					 * @brief 设置session
+					 * @param key
+					 * @param value
+					 */
+					static void add_session(std::string const& key, std::any const& value) {
+						current()->add_session(key, value);
+					}
+					/**
+					 * @brief 添加session并设置权限
+					 * @param key
+					 * @param value
+					 */
+					static void add_authen_session(std::string const& key, std::any const& value) {
+						add_session(key, value);
+						set_authen();
+					}
+					/**
+					 * @brief 获取session
+					 * @param key
+					 * @return
+					 */
+					static std::any& session(std::string const& key) {
+						return current()->session(key);
+					}
+					/**
+					 * @brief 获取session
+					 * @tparam _Ret
+					 * @param key
+					 * @param succ
+					 * @return
+					 */
+					template<typename _Ret>
+					static bool get_session(std::string const& key, _Ret& result) {
+						std::any any_value = current()->session(key);
+						if (any_value.type() != typeid(_Ret)) {
+							return false;
+						}
+						result = std::any_cast<_Ret>(any_value);
+						return true;
+					}
+					/**
+					 * @brief 添加cookie
+					 * @param timeout
+					 */
+					static void add_cookie(int timeout = 30) {
+						current()->add_cookie(timeout);
+					}
+					/**
+					 * @brief 删除cookie
+					 */
+					static void remove_cookie() {
+						current()->remove_cookie();
+					}
+					/**
+					 * @brief 重置cookie
+					 * @param timeout
+					 */
+					static void reset_cookie(int timeout = 30) {
+						remove_cookie();
+						add_cookie(timeout);
+					}
+					/**
+					 * @brief 验证码比较
+					 * @param key
+					 * @param captcha_code
+					 * @return
+					 */
+					static captcha_type captcha_compare(std::string const& key, std::string const& captcha_code) {
+						std::string value;
+						if (!get_session<std::string>(key, value))
+							return mvc::captcha_type::no;
+						else if (v3::utils::case_insensitive_compare(value, captcha_code))
+							return mvc::captcha_type::success;
+						else
+							return mvc::captcha_type::fail;
+					}
+					/**
+					 * @brief 验证码比较
+					 * @param key
+					 * @param captcha_code
+					 * @param success
+					 * @param message
+					 * @return
+					 */
+					static bool captcha_compare(std::string const& key, std::string const& captcha_code, bool& success, std::string& message) {
+						auto result = captcha_compare(key, captcha_code);
+						if (mvc::captcha_type::no == result) {
+							success = false;
+							message = "验证码不存在!";
+							return false;
+						}
+						else if (mvc::captcha_type::fail == result) {
+							success = false;
+							message = "验证码错误!";
+							return false;
+						}
+						else {
+							success = true;
+							message = "成功!";
+							return true;
+						}
+					}
+				};
+				/**
+				 * @brief
+				 */
+				static void new_curr_http_context(http::web_request& req, http::web_response& rep) {
+					rep.clear();
+					new http_context(req, rep);
+				}
+				/**
+				 * @brief
+				 */
+				static void remove_curr_http_context() {
+					std::lock_guard<std::mutex> locker(mutex_);
+					http_context_list_.erase(std::this_thread::get_id());
+				}
+				/**
+				 * @brief
+				 * @param route
+				 * @return
+				 */
+				static std::shared_ptr<http_context> current() {
+					std::lock_guard<std::mutex> locker(mutex_);
+					return http_context_list_[std::this_thread::get_id()];
+				}
+				/**
+				 * @brief
+				 */
+				bool authen() {
+					if (current_session_)
+						return current_session_->authen;
+					return false;
+				}
+				/**
+				 * @brief
+				 */
+				void set_authen(bool value = true) {
+					if (current_session_)
+						current_session_->authen = value;
+				}
+				/**
+				 * @brief
+				 */
+				void add_session(std::string const& key, std::any const& value) {
+					if (!current_session_)
+						throw std::runtime_error("not cookie!");
+					current_session_->user_data[key] = value;
+				}
+				/**
+				 * @brief
+				 */
+				std::any& session(std::string const& key) {
+					static std::any g_any;
+					if (current_session_) {
+						if (current_session_->user_data.find(key) != current_session_->user_data.end()) {
+							return current_session_->user_data[key];
+						}
+					}
+					g_any = std::any();
+					return g_any;
+				}
+				/**
+				 * @brief
+				 */
+				void add_cookie(int timeout = 30) {
+					std::shared_ptr<cookie> item(new cookie);
+					item->time = timeout * (1000 * 60);
+					item->last_expire_time = v3::datetime::current_time_stamp() + item->time;
+					if (current_session_ && !current_session_->close) {
+						if (!current_session_->cookies_)
+							current_session_->cookies_.reset(new cookies);
+						current_session_->cookies_->add(item);
+					}
+					else {
+						current_session_.reset(new mvc::session);
+						current_session_->cookies_.reset(new cookies);
+						current_session_->cookies_->add(item);
+						mvc::sessions::add_session(current_session_);
+					}
+					std::string set_cookie_str;
+					set_cookie_str += item->name;
+					set_cookie_str += "=";
+					set_cookie_str += item->value;
+					set_cookie_str += ";";
+					set_cookie_str += item->path;
+					response.set(http::field::set_cookie, set_cookie_str);
+				}
+				/**
+				 * @brief
+				 */
+				void remove_cookie() {
+					if (current_session_) {
+						current_session_->close = true;
+					}
+					response.set(http::field::set_cookie, "SessionId=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT");
+				}
+				/**
+				 * @brief
+				 */
+				void set_controller_action(std::shared_ptr<controller_action> value) {
+					controller_action_ = value;
+				}
+				/**
+				 * @brief
+				 */
+				std::shared_ptr<controller_action> get_controller_action() {
+					return controller_action_;
+				}
+				/**
+				 * @brief
+				 */
+				http::web_request& request;
+				/**
+				 * @brief
+				 */
+				http::web_response& response;
+				/**
+				 * @brief
+				 */
+				std::filesystem::path root_directory;
+			private:
+				http_context(http::web_request& req, http::web_response& rep) :
+					request(req),
+					response(rep),
+					root_directory(rep.get_root_directory()) {
+					if (req.find(http::field::cookie) != req.end()) {
+						current_session_ = sessions::get_session(std::string(req.find(http::field::cookie)->value().begin(), req.find(http::field::cookie)->value().end()));
+					}
+					std::lock_guard<std::mutex> locker(mutex_);
+					http_context_list_[std::this_thread::get_id()].reset(this);
+				}
+			private:
+				std::shared_ptr<mvc::session> current_session_;
+				std::shared_ptr<controller_action> controller_action_;
+			private:
+				static std::mutex												mutex_;
+				static std::map<std::thread::id, std::shared_ptr<http_context>> http_context_list_;
+			};
+
+			class http_context_gc {
+			public:
+				http_context_gc(http::web_request& req, http::web_response& rep) {
+					http_context::new_curr_http_context(req, rep);
+				}
+				virtual ~http_context_gc() {
+					http_context::remove_curr_http_context();
+				}
+			};
+
+			enum class pseudo_type {
+				NON = 0,
+				MASK,
+				MODEL,
+				FOR,
+				IF,
+				SWITCH,
+				FILE
+			};
+
+			struct class_value {
+				bool is_list = false;
+				std::string class_name;
+				std::vector<std::map<std::string, std::string>> class_value;
+			};
+
+			struct ipseudo_label {
+				ipseudo_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
+					type(value_type.first),
+					label(value_type.second) {
+				}
+				/**
+				 * @brief 类型
+				 */
+				pseudo_type										type;
+				/**
+				 * @brief 原始代码
+				 */
+				std::string										html_code;
+				/**
+				 * @brief 临时原始代码
+				 */
+				std::string										html_code_tmp;
+				/**
+				 * @brief 类名
+				 */
+				std::string										class_name;
+				/**
+				 * @brief 标签
+				 */
+				std::pair<std::string, std::string>				label;
+				/**
+				 * @brief 实体类数据列表
+				 */
+				std::vector<std::map<std::string, std::string>> class_value_list;
+				/**
+				 * @brief 子标签
+				 */
+				std::vector<std::shared_ptr<ipseudo_label>>		childs;
+				/**
+				 * @brief 解析返回html
+				 */
+				virtual std::string analysis() = 0;
+				/**
+				 * @brief 设置属性值
+				 */
+				void set_class_value(std::vector<std::shared_ptr<class_value>>const& value) {
+					for (auto it : childs) {
+						it->set_class_value(value);
+					}
+					for (auto it : value) {
+						if (class_name != it->class_name)
+							continue;
+						if (it->is_list && type == pseudo_type::FOR) {
+							class_value_list = it->class_value;
+							break;
+						}
+						else if (!it->is_list) {
+							class_value_list = it->class_value;
+							break;
+						}
+					}
+				}
+				/**
+				 * @brief 解析基础信息
+				 */
+				virtual void analysis_baseinfo() = 0;
+			protected:
+				std::string extract(std::string const& value, std::pair<std::string, std::string> const& pair, int& index) {
+					std::string result;
+					bool ok = false;
+					int count = 0;
+					for (size_t i = 0; i < value.size(); ++i) {
+						if (i + 1 >= pair.first.size() &&
+							value[i] == pair.first[pair.first.size() - 1] &&
+							value.substr(i - pair.first.size() + 1, pair.first.size()) == pair.first) {
+							count++;
+							if (count == 1) {
+								ok = true;
+								continue;
+							}
+						}
+						if (ok &&
+							value.size() >= i + pair.second.size() &&
+							value[i] == pair.second[0] &&
+							value.substr(i, pair.second.size()) == pair.second) {
+							count--;
+							if (count == 0) {
+								index = i + 1;
+								return result;
+							}
+						}
+						if (ok) {
+							result += value[i];
+						}
+					}
+					index = -1;
+					return result;
+				}
+				std::vector<std::string> extractList(std::string const& value, std::pair<std::string, std::string> const& pair) {
+					std::vector<std::string> result;
+					int index = 0;
+					int pos = 0;
+					while (index > -1) {
+						pos += index;
+						std::string ret = extract(value.substr(pos, value.size() - pos), pair, index);
+						if (index != -1)
+							result.push_back(ret);
+					}
+					return result;
+				}
+			};
+
+			struct pseudo_mask_label : public ipseudo_label {
+				pseudo_mask_label(std::pair<pseudo_type, std::pair<std::string, std::string>>const& value_type) :
+					ipseudo_label(value_type) {
+				}
+				std::string mask_name;
+				virtual std::string analysis()override {
+					for (auto child : childs) {
+						std::string childValue = child->analysis();
+						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
+					}
+					int index = 0;
+					std::string header = extract(html_code_tmp, { "${mask","}" }, index);
+					header = "${mask" + header + "}";
+					std::string tmp = extract(html_code_tmp, { header,"{/mask}" }, index);
+					return tmp;
+				}
+				virtual void analysis_baseinfo() override {
+					html_code_tmp = html_code;
+					for (auto child : childs) {
+						child->analysis_baseinfo();
+					}
+					//获取mask名称
+					int index = 0;
+					mask_name = extract(html_code, { "name='","'" }, index);
+				}
+			};
+
+			struct pseudo_model_label : public ipseudo_label {
+				pseudo_model_label(std::pair<pseudo_type, std::pair<std::string, std::string>>const& value_type) :
+					ipseudo_label(value_type) {
+				}
+				virtual std::string analysis()override {
+					for (auto child : childs) {
+						std::string childValue = child->analysis();
+						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
+					}
+					std::string propName;
+					std::string propValue;
+					std::map<std::string, std::string> mapPropValue;
+					{
+						int index = 0;
+						std::string tmp = extract(html_code_tmp, { "name='","'" }, index);
+						std::string::size_type pos = tmp.find('.');
+						if (pos != std::string::npos) {
+							propName = tmp.substr(pos + 1, tmp.size() - pos - 1);
+						}
+					}
+					//获取值
+					{
+						int index = 0;
+						std::string tmp = extract(html_code_tmp.substr(index, html_code_tmp.size() - index), { "value='[","]'" }, index);
+						//属性值
+						if (tmp == "#value") {
+							propValue = tmp;
+						}
+						else {
+							auto values = v3::utils::split(tmp, ",");
+							for (auto value : values) {
+								auto valueItem = v3::utils::split(value, ":");
+								if (valueItem.size() == 2) {
+									if (valueItem[0].size() >= 2 && valueItem[1].size() >= 2 &&
+										valueItem[0][0] == '\'' && valueItem[0][valueItem[0].size() - 1] == '\'' &&
+										valueItem[1][0] == '\'' && valueItem[1][valueItem[1].size() - 1] == '\'') {
+										valueItem[0].erase(valueItem[0].begin());
+										valueItem[0].erase(valueItem[0].begin() + valueItem[0].size() - 1);
+										valueItem[1].erase(valueItem[1].begin());
+										valueItem[1].erase(valueItem[1].begin() + valueItem[1].size() - 1);
+										mapPropValue[valueItem[0]] = valueItem[1];
+									}
+								}
+							}
+						}
+					}
+					if (propName.empty()) {
+						return "";
+					}
+					//属性值
+					if (!propValue.empty() && !class_value_list.empty()) {
+						if (class_value_list[0].find(propName) != class_value_list[0].end()) {
+							return class_value_list[0][propName];
+						}
+					}
+					else if (!mapPropValue.empty() && !class_value_list.empty()) {
+						if (class_value_list[0].find(propName) != class_value_list[0].end()) {
+							std::string value = class_value_list[0][propName];
+							//选择值
+							if (mapPropValue.find(value) != mapPropValue.end()) {
+								return mapPropValue[value];
+							}
+							//默认值
+							else if (mapPropValue.find("default") != mapPropValue.end()) {
+								if (mapPropValue["default"] == "#value") {
+									return class_value_list[0][propName];
+								}
+								else {
+									return mapPropValue["default"];
+								}
+							}
+						}
+					}
+					return "";
+				}
+				virtual void analysis_baseinfo() override {
+					html_code_tmp = html_code;
+					for (auto child : childs) {
+						child->analysis_baseinfo();
+					}
+					//获取类名属性名
+					int index = 0;
+					std::string tmp = extract(html_code, { "name='","'" }, index);
+					std::string::size_type pos = tmp.find('.');
+					if (pos != std::string::npos) {
+						class_name = tmp.substr(0, pos);
+					}
+				}
+			};
+
+			struct pseudo_for_label : public ipseudo_label {
+				pseudo_for_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
+					ipseudo_label(value_type) {
+				}
+				virtual std::string analysis()override {
+					for (auto child : childs) {
+						std::string childValue = child->analysis();
+						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
+					}
+					std::string resultValue;
+					std::string itemName;
+					std::string forLabel;
+					std::vector<std::string> forItemLabelList;
+					std::map<std::string, std::map<std::string, std::map<std::string, std::string>>> forItemLabelValueList;
+					//获取ITEM名称
+					{
+						int index = 0;
+						itemName = extract(html_code_tmp, { "item='","'" }, index);
+						if (itemName.empty())
+							return "";
+					}
+
+					//提取for标签值
+					{
+						int index = 0;
+						std::string header = extract(html_code_tmp, { "${for","}" }, index);
+						header = "${for" + header + "}";
+						forLabel = extract(html_code_tmp, { header,"{/for}" }, index);
+					}
+
+					//提取foritem标签
+					{
+						forItemLabelList = extractList(forLabel, { "{item","/}" });
+						for (auto& it : forItemLabelList) {
+							it = "{item" + it + "/}";
+						}
+						if (forItemLabelList.empty())
+							return forLabel;
+					}
+
+					//提取foritem参数
+					{
+						int index = 0;
+						std::string header = "name='" + itemName + ".";
+						for (auto it : forItemLabelList) {
+							std::string propName = extract(it, { header,"'" }, index);
+							if (propName.empty())
+								continue;
+							std::string value = extract(it, { "value='[","]'" }, index);
+							if (value.empty())
+								continue;
+							if (value == "#value") {
+								forItemLabelValueList[it][propName][value] = value;
+							}
+							else {
+								auto values = v3::utils::split(value, ",");
+								for (auto valueIt : values) {
+									auto valueItem = v3::utils::split(valueIt, "':'");
+									if (valueItem.size() == 2) {
+										valueItem[0] += "'";
+										valueItem[1] = "'" + valueItem[1];
+										if (valueItem[0].size() >= 2 && valueItem[1].size() >= 2 &&
+											valueItem[0][0] == '\'' && valueItem[0][valueItem[0].size() - 1] == '\'' &&
+											valueItem[1][0] == '\'' && valueItem[1][valueItem[1].size() - 1] == '\'') {
+
+											valueItem[0].erase(valueItem[0].begin());
+											valueItem[0].erase(valueItem[0].begin() + valueItem[0].size() - 1);
+
+											valueItem[1].erase(valueItem[1].begin());
+											valueItem[1].erase(valueItem[1].begin() + valueItem[1].size() - 1);
+
+											forItemLabelValueList[it][propName][valueItem[0]] = valueItem[1];
+										}
+									}
+								}
+							}
+						}
+					}
+
+					//遍历值
+					{
+						int index = 0;
+						for (auto item : class_value_list) {
+							index++;
+							std::string itemValue = forLabel;
+							for (auto forItem : forItemLabelList) {
+								//没有查找到值赋值为空
+								if (forItemLabelValueList.find(forItem) == forItemLabelValueList.end()) {
+									itemValue = v3::utils::replace(itemValue, forItem, "");
+									continue;
+								}
+								//查找属性
+								if (forItemLabelValueList[forItem].find("for-index") != forItemLabelValueList[forItem].end()) {
+
+									//默认值
+									if (forItemLabelValueList[forItem]["for-index"].find("#value") != forItemLabelValueList[forItem]["for-index"].end()) {
+
+										itemValue = v3::utils::replace(itemValue, forItem, std::to_string(index));
+									}
+									else {
+										if (forItemLabelValueList[forItem]["for-index"].find(std::to_string(index)) != forItemLabelValueList[forItem]["for-index"].end()) {
+
+											itemValue = v3::utils::replace(itemValue, forItem, forItemLabelValueList[forItem]["for-index"][std::to_string(index)]);
+										}
+										else if (forItemLabelValueList[forItem]["for-index"].find("default") != forItemLabelValueList[forItem]["for-index"].end()) {
+											itemValue = v3::utils::replace(itemValue, forItem, forItemLabelValueList[forItem]["for-index"]["default"]);
+										}
+										else {
+											itemValue = v3::utils::replace(itemValue, forItem, "");
+										}
+									}
+									continue;
+								}
+								else {
+									std::string propNameItem;
+									std::map<std::string, std::string> propValueItem;
+									auto childItem = forItemLabelValueList[forItem];
+									for (auto childItemIt : childItem) {
+										propNameItem = childItemIt.first;
+										propValueItem = childItemIt.second;
+									}
+									if (propNameItem.empty()) {
+										itemValue = v3::utils::replace(itemValue, forItem, "");
+										continue;
+									}
+									if (item.find(propNameItem) != item.end()) {
+										if (item.find(propNameItem) != item.end()) {
+											if (propValueItem.find("#value") != propValueItem.end()) {
+												itemValue = v3::utils::replace(itemValue, forItem, item[propNameItem]);
+											}
+											else if (propValueItem.find(item[propNameItem]) != propValueItem.end()) {
+												itemValue = v3::utils::replace(itemValue, forItem, propValueItem[item[propNameItem]]);
+											}
+											else if (propValueItem.find("default") != propValueItem.end()) {
+
+												if (propValueItem["default"] == "#value") {
+													itemValue = v3::utils::replace(itemValue, forItem, item[propNameItem]);
+												}
+												else {
+													itemValue = v3::utils::replace(itemValue, forItem, propValueItem["default"]);
+												}
+											}
+											else {
+												itemValue = v3::utils::replace(itemValue, forItem, "");
+											}
+										}
+										else {
+											itemValue = v3::utils::replace(itemValue, forItem, "");
+										}
+									}
+									else {
+										itemValue = v3::utils::replace(itemValue, forItem, "");
+									}
+								}
+							}
+							resultValue += itemValue;
+						}
+					}
+					return resultValue;
+				}
+				virtual void analysis_baseinfo() override {
+					html_code_tmp = html_code;
+					for (auto child : childs) {
+						child->analysis_baseinfo();
+					}
+					//获取类名属性名
+					int index = 0;
+					class_name = extract(html_code, { "list='","'" }, index);
+				}
+			};
+
+			struct pseudo_if_label : public ipseudo_label {
+				pseudo_if_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
+					ipseudo_label(value_type) {
+				}
+				virtual std::string analysis()override {
+					for (auto child : childs) {
+						std::string childValue = child->analysis();
+						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
+					}
+					std::string propName;
+					std::string propValue;
+					std::string symbol;
+					std::vector<std::string> labelValue;
+					//提取标签内容
+					{
+						labelValue = extractList(html_code_tmp, { "}","{" });
+						if (labelValue.empty())
+							return "";
+					}
+					//判断结构体是否有值
+					{
+						if (class_value_list.empty()) {
+							if (labelValue.size() == 2) {
+								return labelValue[1];
+							}
+							return "";
+						}
+					}
+					//获取类名属性名
+					{
+						int index = 0;
+						std::string tmp = extract(html_code_tmp, { "name='","'" }, index);
+						std::string::size_type pos = tmp.find('.');
+						if (pos != std::string::npos) {
+							propName = tmp.substr(pos + 1, tmp.size() - pos - 1);
+						}
+					}
+					//判断类名
+					{
+						if (propName.empty()) {
+							if (labelValue.size() == 2) {
+								return labelValue[1];
+							}
+							return "";
+						}
+					}
+					//判断属性名称是否存在
+					{
+						if (class_value_list[0].find(propName) == class_value_list[0].end()) {
+							if (labelValue.size() == 2) {
+								return labelValue[1];
+							}
+							return "";
+						}
+					}
+					//提取操作符 逻辑对比值
+					{
+						int index = 0;
+						propValue = extract(html_code_tmp, { "value=='","'" }, index);
+						//==
+						if (propValue.empty()) {
+							propValue = extract(html_code_tmp, { "value!='","'" }, index);
+							//!=
+							if (propValue.empty()) {
+								propValue = extract(html_code_tmp, { "value>='","'" }, index);
+								//>=
+								if (propValue.empty()) {
+									propValue = extract(html_code_tmp, { "value<='","'" }, index);
+									//<=
+									if (propValue.empty()) {
+										if (labelValue.size() == 2) {
+											return labelValue[1];
+										}
+										return "";
+									}
+									else
+										symbol = "<=";
+								}
+								else
+									symbol = ">=";
+							}
+							else
+								symbol = "!=";
+						}
+						else
+							symbol = "==";
+					}
+					//判断
+					{
+						if (symbol == "==" && propValue.compare(class_value_list[0][propName]) == 0) {
+							return labelValue[0];
+						}
+						else if (symbol == "!=" && propValue.compare(class_value_list[0][propName]) != 0) {
+							return labelValue[0];
+						}
+						else if (symbol == ">=" && propValue.compare(class_value_list[0][propName]) >= 0) {
+							return labelValue[0];
+						}
+						else if (symbol == "<=" && propValue.compare(class_value_list[0][propName]) <= 0) {
+							return labelValue[0];
+						}
+						else {
+							if (labelValue.size() == 2)
+								return labelValue[1];
+						}
+					}
+					return "";
+				}
+				virtual void analysis_baseinfo() override {
+					html_code_tmp = html_code;
+					for (auto child : childs) {
+						child->analysis_baseinfo();
+					}
+					//获取类名属性名
+					int index = 0;
+					std::string tmp = extract(html_code, { "name='","'" }, index);
+					std::string::size_type pos = tmp.find('.');
+					if (pos != std::string::npos) {
+						class_name = tmp.substr(0, pos);
+					}
+				}
+			};
+
+			struct pseudo_switch_label : public ipseudo_label {
+				pseudo_switch_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
+					ipseudo_label(value_type) {
+				}
+				virtual std::string analysis()override {
+					for (auto child : childs) {
+						std::string childValue = child->analysis();
+						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
+					}
+					std::string propName;
+					std::string labelValueDefault;
+					std::vector<std::string> labelValue;
+
+					//获取类名属性名
+					{
+						int index = 0;
+						std::string tmp = extract(html_code_tmp, { "name='","'" }, index);
+						std::string::size_type pos = tmp.find('.');
+						if (pos != std::string::npos) {
+							propName = tmp.substr(pos + 1, tmp.size() - pos - 1);
+						}
+					}
+
+					//提取标签内容
+					{
+						int index = 0;
+						labelValue = extractList(html_code_tmp, { "{case","/case}" });
+						labelValueDefault = extract(html_code_tmp, { "{default}","{/default}" }, index);
+						if (labelValue.empty() && labelValueDefault.empty()) {
+							return "";
+						}
+						else if (labelValue.empty() && !labelValueDefault.empty()) {
+							if (labelValueDefault.find("#value") != std::string::npos) {
+								if (class_value_list.empty())
+									return "";
+								if (propName.empty())
+									return "";
+								if (class_value_list[0].find(propName) == class_value_list[0].end())
+									return "";
+								return class_value_list[0][propName];
+							}
+							return labelValueDefault;
+						}
+					}
+
+					//判断属性值
+					{
+						if (class_value_list.empty()) {
+							if (labelValueDefault.empty())
+								return "";
+							if (labelValueDefault.find("#value") != std::string::npos)
+								return "";
+							return labelValueDefault;
+						}
+
+						if (propName.empty()) {
+							if (labelValueDefault.empty())
+								return "";
+							if (labelValueDefault.find("#value") != std::string::npos)
+								return "";
+							return labelValueDefault;
+						}
+
+						if (class_value_list[0].find(propName) == class_value_list[0].end()) {
+							if (labelValueDefault.empty())
+								return "";
+							if (labelValueDefault.find("#value") != std::string::npos)
+								return "";
+							return labelValueDefault;
+						}
+					}
+
+					//遍历值
+					{
+						for (auto it : labelValue) {
+							int index = 0;
+							std::string propValue = extract(it, { "value='","'" }, index);
+							if (class_value_list[0][propName] == propValue) {
+								return extract(it, { "}","{" }, index);
+							}
+						}
+					}
+
+					//判断默认值
+					{
+						if (labelValueDefault.empty())
+							return "";
+						if (labelValueDefault.find("#value") != std::string::npos) {
+							return v3::utils::replace(labelValueDefault, "#value", class_value_list[0][propName]);
+						}
+						return labelValueDefault;
+					}
+				}
+				virtual void analysis_baseinfo() override {
+					html_code_tmp = html_code;
+					for (auto child : childs) {
+						child->analysis_baseinfo();
+					}
+					//获取类名属性名
+					int index = 0;
+					std::string tmp = extract(html_code, { "name='","'" }, index);
+					std::string::size_type pos = tmp.find('.');
+					if (pos != std::string::npos) {
+						class_name = tmp.substr(0, pos);
+					}
+				}
+			};
+
+			struct pseudo_file_label : public ipseudo_label {
+				pseudo_file_label(std::pair<pseudo_type, std::pair<std::string, std::string>> const& value_type) :
+					ipseudo_label(value_type) {
+				}
+				virtual std::string analysis()override {
+					for (auto child : childs) {
+						std::string childValue = child->analysis();
+						html_code_tmp = v3::utils::replace(html_code_tmp, child->html_code, childValue);
+					}
+					int index = 0;
+					std::string path_tmp = extract(html_code_tmp, { "path='","'" }, index);
+					std::filesystem::path path = path_tmp;
+					std::filesystem::path filepath;
+					filepath = http_context::current()->response.get_root_directory();
+					filepath.make_preferred();
+					filepath /= path.make_preferred().relative_path();
+					if (filepath.empty())
+						return "";
+					if (std::filesystem::exists(filepath)) {
+						std::ifstream file(filepath, std::ios::in);
+						if (file.is_open()) {
+							return std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
+						}
+					}
+					return "";
+				}
+				virtual void analysis_baseinfo() override {
+					html_code_tmp = html_code;
+					for (auto child : childs) {
+						child->analysis_baseinfo();
+					}
+				}
+			};
+
+			struct pseudo_extract_class_value {
+				template<typename ..._Args>
+				static std::vector<std::shared_ptr<class_value>> get_class_value(_Args&&...args) {
+					std::vector<std::shared_ptr<class_value>> result;
+					auto tuple = std::forward_as_tuple(std::forward<_Args>(args)...);
+					v3::utils::for_each(tuple, [&](auto& it) {
+						auto value = serialize(it);
+						result.push_back(value); });
+					return result;
+				}
+			private:
+				static std::string get_prop_value(rttr::variant const& value) {
+					std::string result;
+					if (value.get_type() == rttr::type::get<int>()) {
+						result = std::to_string(value.get_value<int>());
+					}
+					else if (value.get_type() == rttr::type::get<std::int64_t>()) {
+						result = std::to_string(value.get_value<std::int64_t>());
+					}
+					else if (value.get_type() == rttr::type::get<float>()) {
+						result = v3::utils::format("{:.2f}", value.get_value<float>());
+					}
+					else if (value.get_type() == rttr::type::get<double>()) {
+						result = v3::utils::format("{:.2f}", value.get_value<double>());
+					}
+					else if (value.get_type() == rttr::type::get<long>()) {
+						result = std::to_string(value.get_value<long>());
+					}
+					else if (value.get_type() == rttr::type::get<bool>()) {
+						if (value.get_value<bool>())
+							result = "true";
+						else
+							result = "false";
+					}
+					else if (value.get_type() == rttr::type::get<std::string>()) {
+						result = value.get_value<std::string>();
+					}
+					else if (value.get_type() == rttr::type::get<v3::datetime>()) {
+						auto t = value.get_value<v3::datetime>();
+						result = t.to_string();
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<int>>()) {
+						auto values = value.get_value<std::vector<int>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += std::to_string(values[i]);
+							}
+							else {
+								result += std::to_string(values[i]) + ",";
+							}
+						}
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<std::int64_t>>()) {
+						auto values = value.get_value<std::vector<std::int64_t>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += std::to_string(values[i]);
+							}
+							else {
+								result += std::to_string(values[i]) + ",";
+							}
+						}
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<float>>()) {
+						auto values = value.get_value<std::vector<float>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += v3::utils::format("{:.2f}", values[i]);
+							}
+							else {
+								result += v3::utils::format("{:.2f}", values[i]) + ",";
+							}
+						}
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<double>>()) {
+						auto values = value.get_value<std::vector<double>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += v3::utils::format("{:.2f}", values[i]);
+							}
+							else {
+								result += v3::utils::format("{:.2f}", values[i]) + ",";
+							}
+						}
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<long>>()) {
+						auto values = value.get_value<std::vector<long>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += std::to_string(values[i]);
+							}
+							else {
+								result += std::to_string(values[i]) + ",";
+							}
+						}
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<bool>>()) {
+						auto values = value.get_value<std::vector<bool>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += values[i] ? "true" : "false";
+							}
+							else {
+								result += values[i] ? "true," : "false,";
+							}
+						}
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<std::string>>()) {
+						auto values = value.get_value<std::vector<std::string>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += values[i];
+							}
+							else {
+								result += values[i] + ",";
+							}
+						}
+					}
+					else if (value.get_type() == rttr::type::get<std::vector<v3::datetime>>()) {
+						auto values = value.get_value<std::vector<v3::datetime>>();
+						for (int i = 0; i < values.size(); ++i) {
+							if (i + 1 == values.size()) {
+								result += values[i].to_string();
+							}
+							else {
+								result += values[i].to_string() + ",";
+							}
+						}
+					}
+					return result;
+				}
+				template<typename _Type>
+				static std::shared_ptr<class_value> serialize(std::vector<std::shared_ptr<_Type>> const& values) {
+					std::vector<_Type> valueTmp;
+					for (auto it : values) {
+						valueTmp.push_back(*it);
+					}
+					return serialize(valueTmp);
+				}
+				template<typename _Type>
+				static std::shared_ptr<class_value> serialize(std::vector<_Type*> values) {
+					std::vector<_Type> valueTmp;
+					for (auto it : values) {
+						valueTmp.push_back(*it);
+					}
+					return serialize(valueTmp);
+				}
+				template<typename _Type>
+				static std::shared_ptr<class_value> serialize(std::vector<_Type> values) {
+					std::shared_ptr<class_value> result(new class_value);
+					rttr::type type = rttr::type::get<_Type>();
+					std::string className(type.get_name());
+					result->class_name = className;
+					result->is_list = true;
+					for (auto it : values) {
+						std::map<std::string, std::string> elem = web_reflect::get_object_value(it);
+						result->class_value.push_back(elem);
+					}
+					return result;
+				}
+				template<typename _Type>
+				static std::shared_ptr<class_value> serialize(std::shared_ptr<_Type> value) {
+					return serialize(*value);
+				}
+				template<typename _Type>
+				static std::shared_ptr<class_value> serialize(_Type* value) {
+					return serialize(*value);
+				}
+				template<typename _Type>
+				static std::shared_ptr<class_value> serialize(_Type value) {
+					std::shared_ptr<class_value> result(new class_value);
+					rttr::type type = rttr::type::get<_Type>();
+					std::string className(type.get_name());
+					result->class_name = className;
+					result->is_list = false;
+					std::map<std::string, std::string> elem = web_reflect::get_object_value(value);
+					result->class_value.push_back(elem);
+					return result;
+				}
+			};
+
+			struct pseudo_extract_label_value {
+				/*
+				* 伪代码结构
+				* 可嵌套 避开关键字 [' }]
+				* ${model name='test_info.userName' value='['${model name='test_info.id' value='[#value]'/}':'启用','false':'禁用'/}
+				*
+				* switch case 中不能存在 #value 属性值  default可以有默认值 可以有固定值
+				* ${switch name='test_info.id'}{case value='1'}<h1>值1</h1>{/case}...{default}<h1>#value</h1>{/default}{/switch}
+				*
+				* if 运算符 == != >= <=
+				* ${if name='test_info.id' value=='100'}<p>判断正确</p>{else}<p>判断错误</p>{/if}
+				*
+				* for for-index 从1开始
+				* ${for item='item' list='test_info'} <td>{item name='item.for-index' value='[#value]'/}</td><td>{item name='item.enable' value='['true':'启用','default':'#value']'/}</td>{/for}
+				*
+				* file path 可以固定 可以嵌套 model设置html路径
+				* ${file path='C:/Users/86158/Desktop/404.html'/}
+				*/
+				static std::vector<std::shared_ptr<ipseudo_label>> analysis(std::string const& html) {
+					std::vector<std::shared_ptr<ipseudo_label>> result;
+					std::pair<std::string, std::string> type = { "${mask","{/mask}" };
+					for (size_t i = 0; i < html.size(); ++i) {
+						if (html.size() > i + type.first.size() &&
+							html[i] == type.first[0] &&
+							html.substr(i, type.first.size()) == type.first) {
+
+							std::string retHtml = nounanalysis(html.substr(i, html.size() - i), result);
+							result[result.size() - 1]->html_code;
+							i += retHtml.size();
+						}
+					}
+					for (auto it : result) {
+						it->analysis_baseinfo();
+					}
+					return result;
+				}
+			private:
+				static std::string nounanalysis(std::string const& html, std::vector<std::shared_ptr<ipseudo_label>>& childs, pseudo_type type = pseudo_type::MASK) {
+					static std::map<pseudo_type, std::pair<std::string, std::string>> g_pseudoLabel = {
+						{
+							pseudo_type::MASK,
+							{"${mask","{/mask}"}
+						},
+						{
+							pseudo_type::MODEL,
+							{"${model","/}"}
+						},
+						{
+							pseudo_type::SWITCH,
+							{"${switch","{/switch}"}
+						},
+						{
+							pseudo_type::IF,
+							{"${if","{/if}"}
+						},
+						{
+							pseudo_type::FOR,
+							{"${for","{/for}"}
+						},
+						{
+							pseudo_type::FILE,
+							{"${file","/}"}
+						}
+					};
+					if (!(html.size() > g_pseudoLabel[type].first.size() &&
+						html.substr(0, g_pseudoLabel[type].first.size()) == g_pseudoLabel[type].first)) {
+						return "";
+					}
+					if (type == pseudo_type::MASK)
+						childs.push_back(std::make_shared<pseudo_mask_label>(*g_pseudoLabel.find(type)));
+					else if (type == pseudo_type::MODEL)
+						childs.push_back(std::make_shared<pseudo_model_label>(*g_pseudoLabel.find(type)));
+					else if (type == pseudo_type::FOR)
+						childs.push_back(std::make_shared<pseudo_for_label>(*g_pseudoLabel.find(type)));
+					else if (type == pseudo_type::IF)
+						childs.push_back(std::make_shared<pseudo_if_label>(*g_pseudoLabel.find(type)));
+					else if (type == pseudo_type::SWITCH)
+						childs.push_back(std::make_shared<pseudo_switch_label>(*g_pseudoLabel.find(type)));
+					else if (type == pseudo_type::FILE)
+						childs.push_back(std::make_shared<pseudo_file_label>(*g_pseudoLabel.find(type)));
+					for (std::string::size_type i = 0; i < html.size(); ++i) {
+						for (auto pseudo : g_pseudoLabel) {
+							if (html.size() > i + pseudo.second.first.size() &&
+								html[i] == pseudo.second.first[0] &&
+								html.substr(i, pseudo.second.first.size()) == pseudo.second.first) {
+								if (i == 0) {
+									break;
+								}
+								else {
+									std::string retHtml = nounanalysis(html.substr(i, html.size() - i), childs[childs.size() - 1]->childs, pseudo.first);
+									childs[childs.size() - 1]->html_code += retHtml;
+									i += retHtml.size();
+								}
+							}
+						}
+						if (type != pseudo_type::NON) {
+							childs[childs.size() - 1]->html_code += html[i];
+						}
+						if (childs[childs.size() - 1]->html_code.size() > g_pseudoLabel[type].second.size() &&
+							childs[childs.size() - 1]->html_code.substr(childs[childs.size() - 1]->html_code.size() - g_pseudoLabel[type].second.size(), g_pseudoLabel[type].second.size()) == g_pseudoLabel[type].second) {
+							return childs[childs.size() - 1]->html_code;
+						}
+					}
+					return "";
+				}
+			};
+
+			enum class from_storage_type {
+				/**
+				 * @brief body
+				*/
+				BODY = 0,
+				/**
+				 * @brief url
+				*/
+				QUERY,
+				/**
+				 * @brief header
+				*/
+				HEADER,
+				/**
+				 * @brief url
+				 */
+				URL
+			};
+
+			enum class argument_type {
+				Json = 0,
+				Multipart,
+				Int,
+				Int64,
+				Float,
+				Double,
+				Long,
+				Bool_,
+				String,
+				DateTime,
+				Binary,
+				VecJson,
+				VecInt,
+				VecInt64,
+				VecFloat,
+				VecDouble,
+				VecLong,
+				VecBool,
+				VecString,
+				VecDateTime
+			};
+
+			enum class http_method {
+				/**
+				 * @brief get
+				*/
+				GET = 0,
+				/**
+				 * @brief post
+				*/
+				POST = 1
+			};
+
+			struct multipart {
+				std::string					content_disposition;
+				std::string					name;
+				std::vector<std::uint8_t>	data;
+				std::string					value;
+				std::string					content_type;
+				std::string					filename;
+				std::string					content_transfer_encoding;
+			};
+
+			struct multipart_value {
+				std::vector<multipart> data;
+				template<typename _Type>
+				_Type value() {
+					_Type result;
+					std::map<std::string, std::string> elem;
+					for (auto value : data) {
+						elem[value.name] = value.value;
+					}
+					web_reflect::set_object_value(result, elem);
+					return result;
+				}
+			};
+
+			struct action_argument {
+				void parameter(http::web_request& request, const rttr::parameter_info& type) {
+					parameter_value_.clear();
+					switch (from_storage_type_) {
+					case from_storage_type::HEADER:  analysis_header(request, type);  return;
+					case from_storage_type::QUERY:   analysis_query(request, type);   return;
+					case from_storage_type::BODY:    analysis_body(request, type);    return;
+					case from_storage_type::URL:     analysis_url(request, type);     return;
+					}
+					throw std::runtime_error("FormStorageType:错误!");
+				}
+				/**
+				 * @brief 参数名称
+				*/
+				std::string					parameter_name_;
+				/**
+				 * @brief 参数
+				*/
+				rttr::variant				parameter_value_;
+				/**
+				 * @brief 数据类型
+				*/
+				argument_type				argument_type_ = argument_type::Binary;
+				/**
+				 * @brief 表单存储类型
+				*/
+				from_storage_type			from_storage_type_ = from_storage_type::QUERY;
+			private:
+				/**
+				 * @brief 解析协议头
+				 * @param request
+				 * @param type
+				*/
+				void analysis_header(http::web_request& request, const rttr::parameter_info& type) {
+					std::map<std::string, std::string> headers;
+					for (auto& it : request) {
+						std::string name(it.name_string().begin(), it.name_string().end());
+						std::string value(it.value().begin(), it.value().end());
+						headers[name] = value;
+					}
+					if (headers.find(parameter_name_) == headers.end())
+						throw std::runtime_error("解析协议头参数错误!");
+					convert(headers[parameter_name_], type);
+				}
+				/**
+				 * @brief 解析url参数
+				 * @param request
+				 * @param type
+				*/
+				void analysis_query(http::web_request& request, const rttr::parameter_info& type) {
+					std::string query(request.query().begin(), request.query().end());
+					std::map<std::string, std::string>  querys = v3::utils::split_http_form(query);
+					if (querys.find(parameter_name_) == querys.end())
+						throw std::runtime_error("解析Query参数错误!");
+					convert(querys[parameter_name_], type);
+				}
+				/**
+				 * @brief 解析BODY
+				 * @param request
+				 * @param type
+				*/
+				void analysis_body(http::web_request& request, const rttr::parameter_info& type) {
+					if (type.get_type() == rttr::type::get<multipart_value>()) {
+						multipart_value parameter;
+						auto multipartValue = request.get_multipart();
+						for (auto it = multipartValue.begin(); it != multipartValue.end(); ++it) {
+							multipart item;
+							item.content_disposition = it->content_disposition();
+							item.name = it->name();
+							auto valueTmp = it->value();
+							item.data.insert(item.data.end(), valueTmp.begin(), valueTmp.end());
+							if (it->filename().empty()) {
+								try {
+									item.value = it->value();
+								}
+								catch (...) {}
+							}
+							item.content_type = it->content_type();
+							item.filename = it->filename();
+							item.content_transfer_encoding = it->content_transfer_encoding();
+							parameter.data.push_back(item);
+						}
+						parameter_value_ = parameter;
+					}
+					else if (parameter_name_.empty()) {
+						convert(std::string(request.body().begin(), request.body().end()), type);
+					}
+					else {
+						std::string body(request.body().begin(), request.body().end());
+						std::map<std::string, std::string> bodys = v3::utils::split_http_form(body);
+						if (bodys.find(parameter_name_) == bodys.end())
+							throw std::runtime_error("解析Body参数错误!");
+						convert(bodys[parameter_name_], type);
+					}
+				}
+				/**
+				 * @brief url
+				 * @param request
+				 * @param type
+				 */
+				void analysis_url(http::web_request& request, const rttr::parameter_info& type) {
+					std::string query(request.find("http_route_parameter")->value());
+					std::map<std::string, std::string>  querys = v3::utils::split_http_form(query);
+					if (querys.find(parameter_name_) == querys.end())
+						throw std::runtime_error("解析Query参数错误!");
+					convert(querys[parameter_name_], type);
+				}
+				/**
+				 * @brief 数据转换
+				 * @param data
+				 * @param type
+				*/
+				void convert(std::string_view data, const rttr::parameter_info& type) {
+					try {
+						switch (argument_type_) {
+						case argument_type::Json: {
+							parameter_value_ = type.get_type().create();
+							v3::json_convert::deserialize(std::string(data.begin(), data.end()), parameter_value_);
+							return;
+						}
+						case argument_type::Multipart: {
+							return;
+						}
+						case argument_type::Int: {
+							parameter_value_ = std::atoi(std::string(data.begin(), data.end()).c_str());
+							return;
+						}
+						case argument_type::Int64: {
+							parameter_value_ = std::atoll(std::string(data.begin(), data.end()).c_str());
+							return;
+						}
+						case argument_type::Float: {
+							parameter_value_ = std::atof(std::string(data.begin(), data.end()).c_str());
+							return;
+						}
+						case argument_type::Double: {
+							parameter_value_ = std::atof(std::string(data.begin(), data.end()).c_str());
+							return;
+						}
+						case argument_type::Long: {
+							parameter_value_ = std::atol(std::string(data.begin(), data.end()).c_str());
+							return;
+						}
+						case argument_type::Bool_: {
+							std::string tmpValue(data.begin(), data.end());
+							parameter_value_ = tmpValue == "1" || tmpValue == "true" || tmpValue == "TRUE" || tmpValue == "True";
+							return;
+						}
+						case argument_type::String: {
+							parameter_value_ = std::string(data.begin(), data.end());
+							return;
+						}
+						case argument_type::DateTime: {
+							parameter_value_ = datetime(std::string(data.begin(), data.end()));
+							return;
+						}
+						case argument_type::Binary: {
+							parameter_value_ = std::vector<std::uint8_t>(data.begin(), data.end());
+							return;
+						}
+						case argument_type::VecInt: {
+							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							std::vector<int> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atoi(vecIt.c_str()));
+							}
+							parameter_value_ = vecValue;
+							return;
+						}
+						case argument_type::VecInt64: {
+							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							std::vector<std::int64_t> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atoll(vecIt.c_str()));
+							}
+							parameter_value_ = vecValue;
+							return;
+						}
+						case argument_type::VecFloat: {
+							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							std::vector<float> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atof(vecIt.c_str()));
+							}
+							parameter_value_ = vecValue;
+							return;
+						}
+						case argument_type::VecDouble: {
+							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							std::vector<double> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atof(vecIt.c_str()));
+							}
+							parameter_value_ = vecValue;
+							return;
+						}
+						case argument_type::VecLong: {
+							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							std::vector<long> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(std::atol(vecIt.c_str()));
+							}
+							parameter_value_ = vecValue;
+							return;
+						}
+						case argument_type::VecBool: {
+							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							std::vector<bool> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(vecIt == "1" || vecIt == "true" || vecIt == "TRUE" || vecIt == "True");
+							}
+							parameter_value_ = vecValue;
+							return;
+						}
+						case argument_type::VecString: {
+							std::vector<std::string> vecValue = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							parameter_value_ = vecValue;
+							return;
+						}
+						case argument_type::VecDateTime: {
+							std::vector<std::string> vec = v3::utils::split(std::string(data.begin(), data.end()), ",");
+							std::vector<datetime> vecValue;
+							for (auto vecIt : vec) {
+								vecValue.push_back(datetime(vecIt));
+							}
+							parameter_value_ = vecValue;
+							return;
+						}
+						}
+					}
+					catch (...) {
+						throw std::runtime_error("解析参数错误");
+					}
+				}
+			};
+
+			struct controller;
+
+			struct controller_action {
+				/**
+				 * @brief 执行动作
+				 * @param request
+				*/
+				rttr::variant invoke(http::web_request& request, rttr::variant& variant, rttr::type const& controller_type) {
+					auto http_current_ptr = http_context::current();
+					//判断contentType
+					std::string content_type = "application/x-www-form-urlencoded";
+					if (request.find(http::field::content_type) != request.end()) {
+						content_type = std::string(request.find(http::field::content_type)->value().begin(), request.find(http::field::content_type)->value().end());
+					}
+					if (content_type.find(content_type) == std::string::npos) {
+						throw std::runtime_error("Content-Type:错误!");
+					}
+					//判断method
+					if (!((method == http_method::GET && request.method() == http::verb::get) || (method == http_method::POST && request.method() == http::verb::post))) {
+						throw std::runtime_error("Method:错误!");
+					}
+					std::vector<rttr::method> find_method;
+					for (auto& it : controller_type.get_methods()) {
+						if (it.get_name() == action_name && it.get_parameter_infos().size() == arguments.size()) {
+							find_method.push_back(it);
+							break;
+						}
+					}
+					if (find_method.empty())
+						throw std::runtime_error("Action:错误!");
+					std::vector<rttr::argument> parameters;
+					std::vector<rttr::variant> variantParameters;
+					{
+						std::lock_guard<std::mutex> locker(mux);
+						for (auto& it : find_method[0].get_parameter_infos()) {
+							arguments[it.get_index()]->parameter(request, it);
+						}
+						for (auto& it : arguments) {
+							variantParameters.push_back(it->parameter_value_);
+						}
+					}
+					for (auto& it : variantParameters) {
+						parameters.push_back(it);
+					}
+					return controller_type.invoke(action_name, variant, parameters);
+				}
+				/**
+				 * @brief 身份验证
+				*/
+				bool											authen = true;
+				/**
+				 * @brief 未登录跳转
+				*/
+				std::string										authen_jump;
+				/**
+				 * @brief 方法名称
+				*/
+				std::string										action_name;
+				/**
+				 * @brief 方式
+				*/
+				http_method										method = http_method::GET;
+				/**
+				 * @brief 数据类型
+				*/
+				std::string										content_type = "application/x-www-form-urlencoded";
+				/**
+				 * @brief 动作类型
+				*/
+				std::string										action_type;
+				/**
+				 * @brief 文件映射
+				*/
+				std::string										file_mapping;
+				/**
+				 * @brief 参数
+				*/
+				std::vector<std::shared_ptr<action_argument>>	arguments;
+				/**
+				 * @brief 控制器
+				*/
+				std::shared_ptr<controller>						parent;
+			private:
+				/**
+				 * @brief 锁
+				*/
+				std::mutex										mux;
+			};
+
+			struct controller {
+				rttr::variant invoke(http::web_request& request) {
+					std::string key(request.find("http_route_key")->value());
+					if (!actions.contains(key))
+						throw std::runtime_error("Action:不存在!");
+					rttr::type type = rttr::type::get_by_name(controller_name);
+					if (!variant.is_valid())
+						variant = type.create();
+					return actions[key]->invoke(request, variant, type);
+				}
+				/**
+				 * @brief 控制器名称
+				*/
+				std::string controller_name;
+				/**
+				 * @brief 动作列表 路由 动作
+				*/
+				std::map<std::string, std::shared_ptr<controller_action>> actions;
+			private:
+				/**
+				 * @brief 对象
+				*/
+				rttr::variant variant;
+			};
+
+			struct mvc_route {
+				bool contains(http::web_request& req) {
+					std::string key;
+					std::string route(req.find("http_route")->value());
+					if (contains(route, key)) {
+						std::size_t index = key.find('<');
+						std::vector<std::string> params;
+						if (std::string::npos != index) {
+							auto keys = v3::utils::split(key.substr(index), "/");
+							auto values = v3::utils::split(route.substr(index), "/");
+							for (int i = 0; i < keys.size() && i < values.size(); ++i) {
+								params.push_back(keys[i].substr(1, keys[i].size() - 2) + "=" + values[i]);
+							}
+						}
+						req.insert("http_route_key", key);
+						req.insert("http_route_parameter", v3::utils::join(params, "&"));
+						return true;
+					}
+					return false;
+				}
+				bool contains(std::string const& route) {
+					std::string key;
+					return contains(route, key);
+				}
+				void add(std::string const& route, std::shared_ptr<controller> value) {
+					routes_[route] = value;
+				}
+				std::shared_ptr<controller>& find(std::string const& route) {
+					std::string key;
+					if (contains(route, key)) {
+						return routes_[key];
+					}
+					throw std::runtime_error("key does not exist");
+				}
+				std::shared_ptr<controller>& operator[](std::string const& route) {
+					return find(route);
+				}
+				std::shared_ptr<controller>& operator[](http::web_request& req) {
+					return find(std::string(req.find("http_route_key")->value()));
+				}
+			private:
+				bool contains(std::string const& route, std::string& result) {
+					if (routes_.contains(route)) {
+						result = route;
+						return true;
+					}
+					else {
+						int slash_count = std::count(route.begin(), route.end(), '/');
+						for (auto& [first, second] : routes_) {
+							std::size_t index = first.find('<');
+							if (std::count(first.begin(), first.end(), '/') == slash_count && index != std::string::npos) {
+								if (first.substr(0, index) == route.substr(0, index)) {
+									result = first;
+									return true;
+								}
+							}
+						}
+						return false;
+					}
+				}
+			private:
+				std::map<std::string, std::shared_ptr<controller>> routes_;
+			};
+
+			struct MVC_API ico_controller {
+				/**
+				 * @brief 注册
+				*/
+				static void attach(std::shared_ptr<controller> controller) {
+					for (auto& [first, second] : controller->actions) {
+						controllers_.add(first, controller);
+					}
+				}
+				/**
+				 * @brief
+				 * @param url
+				 * @return
+				*/
+				static std::shared_ptr<controller> resolve(http::web_request& req) {
+					if (controllers_.contains(req)) {
+						return controllers_[req];
+					}
+					return nullptr;
+				}
+			private:
+				/**
+				 * @brief
+				*/
+				static mvc_route controllers_;
+			};
+
+			struct web_base_response {
+				void set_header(std::string_view name, std::string_view value) {
+					auto& response = http_context::current()->response;
+					response.set(name, value);
+				}
+				void set_header(http::field field, std::string_view value) {
+					auto& response = http_context::current()->response;
+					response.set(field, value);
+				}
+				void set_value(std::string_view value) {
+					auto& response = http_context::current()->response;
+					response.body().file().close();
+					response.body().text() = std::move(value);
+					auto const size = response.body().size();
+					response.content_length(size);
+				}
+				void set_value(std::vector<std::uint8_t> const& value) {
+					auto& response = http_context::current()->response;
+					response.body().file().close();
+					response.body().text() = std::string((char*)&value[0], value.size());
+					auto const size = response.body().size();
+					response.content_length(size);
+				}
+				void set_status(http::status status = http::status::ok) {
+					auto& response = http_context::current()->response;
+					response.result(status);
+				}
+				std::filesystem::path get_root_directory() {
+					auto& response = http_context::current()->response;
+					return response.get_root_directory();
+				}
+				http::status get_status() {
+					auto& response = http_context::current()->response;
+					return response.result();
+				}
+				std::string get_value() {
+					auto& response = http_context::current()->response;
+					return response.body().text();
+				}
+				void prepare_payload() {
+					auto& response = http_context::current()->response;
+					response.prepare_payload();
+				}
+				void chunked(bool value) {
+					auto& response = http_context::current()->response;
+					response.chunked(value);
+				}
+				void set_server(std::string_view value = BEAST_VERSION_STRING) {
+					auto& response = http_context::current()->response;
+					response.set(http::field::server, value);
+				}
+				void set_version(int ver = 11) {
+					auto& response = http_context::current()->response;
+					response.version(ver);
+				}
+				void fill_file(std::filesystem::path const& path, http::status status = http::status::ok) {
+					auto& response = http_context::current()->response;
+					if (path.c_str()[0] == '/' || path.c_str()[0] == '\\') {
+						response.fill_file(path, status);
+					}
+					else {
+						response.fill_file("/" + path.string(), status);
+					}
+				}
+				void fill_html(std::string const& html, http::status status = http::status::ok) {
+					auto& response = http_context::current()->response;
+					response.fill_html(html, status);
+				}
+				void fill_json(std::string const& json, http::status status = http::status::ok) {
+					auto& response = http_context::current()->response;
+					response.fill_json(json, status);
+				}
+				void fill_page(std::string const& value, http::status status = http::status::ok) {
+					auto& response = http_context::current()->response;
+					response.fill_page(status, value);
+				}
+				void fill_text(std::string const& text, http::status status = http::status::ok) {
+					auto& response = http_context::current()->response;
+					response.fill_text(text, status);
+				}
+				void fill_jump(std::string const& url) {
+					set_header(http::field::content_type, http::extension_to_mimetype("html"));
+					set_header(http::field::location, url);
+					set_status(http::status::found);
+				}
+				void fill_stream(std::vector<std::uint8_t> const& data, std::string const& extension, http::status status = http::status::ok) {
+					set_header("Content-Type", http::extension_to_mimetype(extension));
+					set_value(data);
+					set_status(status);
+				}
+				void fill_download(std::filesystem::path const& path, http::status status = http::status::ok) {
+					set_header(http::field::content_type, "application/octet-stream");
+					set_header(http::field::content_disposition, v3::utils::format("attachment; filename={}", path.filename().string()));
+				}
+				void fill_download(std::filesystem::path const& path, std::string const& filename, http::status status = http::status::ok) {
+					set_header(http::field::content_type, "application/octet-stream");
+					set_header(http::field::content_disposition, v3::utils::format("attachment; filename={}", filename));
+				}
+				void fill_view(http::status status = http::status::ok) {
+					fill_file(get_filename(), status);
+				}
+				std::filesystem::path get_filename() {
+					return mvc::http_context::current()->get_controller_action()->file_mapping;
+				}
+			};
+
+			struct web_result_response : public web_base_response {};
+
+			struct unknown_response : public web_base_response {
+				unknown_response(std::string const& text) {
+					set_value(text);
+					set_status(http::status::unknown);
+				}
+				virtual ~unknown_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct jump_response : public web_base_response {
+				jump_response(std::string const& url) {
+					if (!url.empty()) {
+						if (url[0] != '/')
+							fill_jump("/" + url);
+					}
+					else {
+						fill_jump(url);
+					}
+				}
+				virtual ~jump_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct text_response : public web_base_response {
+				text_response(std::string const& text, http::status status = http::status::ok) {
+					fill_text(text, status);
+				}
+				virtual ~text_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct html_response : public web_base_response {
+				html_response(std::string const& html, http::status status = http::status::ok) {
+					fill_html(html, status);
+				}
+				virtual ~html_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct file_response : public web_base_response {
+				file_response() {
+					fill_file(get_filename());
+				}
+				file_response(http::status status = http::status::ok) {
+					fill_file(get_filename(), status);
+				}
+				file_response(std::filesystem::path const& path, http::status status = http::status::ok) {
+					fill_file(path, status);
+				}
+				virtual ~file_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct json_response : public web_base_response {
+				json_response(std::string const& json) {
+					fill_json(json);
+				}
+				json_response(char* json) :
+					json_response(std::string(json)) {
+				}
+				json_response(const char* json) :
+					json_response(std::string(json)) {
+				}
+				template<typename _Type>
+				json_response(_Type const& value) {
+					fill_json(v3::json_convert::serialize(value));
+				}
+				virtual~json_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct stream_response : public web_base_response {
+				stream_response(std::vector<std::uint8_t> const& data, std::string const& extension, http::status status = http::status::ok) {
+					fill_stream(data, extension, status);
+				}
+				virtual~stream_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct download_response : public web_base_response {
+				download_response(std::filesystem::path const& path, http::status status = http::status::ok) {
+					fill_download(path, status);
+				}
+				download_response(std::filesystem::path const& path, std::string const& filename, http::status status = http::status::ok) {
+					fill_download(path, filename, status);
+				}
+				virtual~download_response() {
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			struct view : public web_base_response {
+				virtual ~view() {
+				}
+				view() :
+					web_base_response() {
+					fill_view();
+				}
+				view(std::string const& path) :
+					web_base_response() {
+					fill_file(path);
+				}
+				template<typename ..._Args>
+				view(_Args&& ...args) {
+					std::filesystem::path path = get_filename();
+					std::filesystem::path filepath;
+					filepath = http_context::current()->response.get_root_directory();
+					filepath.make_preferred();
+					filepath /= path.make_preferred().relative_path();
+					std::vector<std::uint8_t> value;
+					std::ifstream file(filepath, std::ios::in | std::ios::binary);
+					if (file.is_open()) {
+						file.seekg(0, std::ios::end);
+						int file_size = file.tellg();
+						file.seekg(0, std::ios::beg);
+						value.resize(file_size);
+						file.read((char*)&value[0], file_size);
+						file.close();
+					}
+					std::string html(value.begin(), value.end());
+					auto label_value_list = pseudo_extract_label_value::analysis(html);
+					if (!label_value_list.empty()) {
+						auto classValueList = pseudo_extract_class_value::get_class_value(std::forward<_Args>(args)...);
+						label_value_list[0]->set_class_value(classValueList);
+						html = label_value_list[0]->analysis();
+						fill_html(html);
+					}
+				}
+				operator web_result_response() {
+					return {};
+				}
+			};
+
+			template<int _Width = 100, int _Height = 38, int _Length = 4, int _Line = 2, int _Spot = 200>
+			struct captcha_response : public v3::mvc::web_base_response {
+				captcha_response(std::string const& session_key = "code") :
+					session_key_(session_key) {
+				}
+				virtual ~captcha_response() {
+				}
+				operator v3::mvc::web_result_response() {
+					//验证码
+					std::string captcha_code = generate_captcha_digits();
+					http_context::current()->add_session(session_key_, captcha_code);
+					std::vector<std::uint8_t> img_vec = generate_captcha_image(captcha_code);
+					return v3::mvc::stream_response(img_vec, "bmp");
+				}
+			private:
+				class CImage : public cimg_library::CImg<unsigned char> {
+				public:
+					CImage(const cimg_library::CImg<unsigned char>& img) :
+						cimg_library::CImg<unsigned char>(img) {}
+					cimg_library::CImg<unsigned char>& save_memory_bmp(std::vector<std::uint8_t>& result) {
+						cimg_library::CImg<ucharT> header(54, 1, 1, 1, 0);
+						unsigned char align_buf[4] = {};
+						const unsigned int
+							align = (4 - (3 * _width) % 4) % 4,
+							buf_size = (3 * _width + align) * height(),
+							file_size = 54 + buf_size;
+						header[0] = 'B'; header[1] = 'M';
+						header[0x02] = file_size & 0xFF;
+						header[0x03] = (file_size >> 8) & 0xFF;
+						header[0x04] = (file_size >> 16) & 0xFF;
+						header[0x05] = (file_size >> 24) & 0xFF;
+						header[0x0A] = 0x36;
+						header[0x0E] = 0x28;
+						header[0x12] = _width & 0xFF;
+						header[0x13] = (_width >> 8) & 0xFF;
+						header[0x14] = (_width >> 16) & 0xFF;
+						header[0x15] = (_width >> 24) & 0xFF;
+						header[0x16] = _height & 0xFF;
+						header[0x17] = (_height >> 8) & 0xFF;
+						header[0x18] = (_height >> 16) & 0xFF;
+						header[0x19] = (_height >> 24) & 0xFF;
+						header[0x1A] = 1;
+						header[0x1B] = 0;
+						header[0x1C] = 24;
+						header[0x1D] = 0;
+						header[0x22] = buf_size & 0xFF;
+						header[0x23] = (buf_size >> 8) & 0xFF;
+						header[0x24] = (buf_size >> 16) & 0xFF;
+						header[0x25] = (buf_size >> 24) & 0xFF;
+						header[0x27] = 0x1;
+						header[0x2B] = 0x1;
+						result.insert(result.end(), reinterpret_cast<std::uint8_t*>(header._data), reinterpret_cast<std::uint8_t*>(header._data) + 64);
+						const unsigned char
+							* ptr_r = data(0, _height - 1, 0, 0),
+							* ptr_g = (_spectrum >= 2) ? data(0, _height - 1, 0, 1) : 0,
+							* ptr_b = (_spectrum >= 3) ? data(0, _height - 1, 0, 2) : 0;
+						switch (_spectrum) {
+						case 1: {
+							cimg_forY(*this, y) {
+								cimg_forX(*this, x) {
+									const unsigned char val = (unsigned char)*(ptr_r++);
+									result.push_back(val); result.push_back(val); result.push_back(val);
+								}
+								result.insert(result.end(), reinterpret_cast<std::uint8_t*>(align_buf), reinterpret_cast<std::uint8_t*>(align_buf) + align);
+								ptr_r -= 2 * _width;
+							}
+						} break;
+						case 2: {
+							cimg_forY(*this, y) {
+								cimg_forX(*this, x) {
+									result.push_back(0);
+									result.push_back((unsigned char)(*(ptr_g++)));
+									result.push_back((unsigned char)(*(ptr_r++)));
+								}
+								result.insert(result.end(), reinterpret_cast<std::uint8_t*>(align_buf), reinterpret_cast<std::uint8_t*>(align_buf) + align);
+								ptr_r -= 2 * _width; ptr_g -= 2 * _width;
+							}
+						} break;
+						default: {
+							cimg_forY(*this, y) {
+								cimg_forX(*this, x) {
+									result.push_back((unsigned char)(*(ptr_b++)));
+									result.push_back((unsigned char)(*(ptr_g++)));
+									result.push_back((unsigned char)(*(ptr_r++)));
+								}
+								result.insert(result.end(), reinterpret_cast<std::uint8_t*>(align_buf), reinterpret_cast<std::uint8_t*>(align_buf) + align);
+								ptr_r -= 2 * _width; ptr_g -= 2 * _width; ptr_b -= 2 * _width;
+							}
+						}
+						}
+						return *this;
+					}
+				};
+			private:
+				//获取验证码
+				std::string generate_captcha_digits() {
+					static const char data_character[] = "23456789abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ\0";
+					int min = 0;
+					int max = std::strlen(data_character) - 1;
+					std::string result;
+					for (int i = 0; i < _Length; ++i) {
+						result += data_character[v3::utils::random(min, max)];
+					}
+					return result;
+				}
+				//生成随机颜色
+				unsigned char* generate_random_color() {
+					static unsigned char colors[][3] = {
+						{47,79,79     },
+						{105,105,105  },
+						{0,0,128      },
+						{100,149,237  },
+						{72,61,139    },
+						{106,90,205   },
+						{123,104,238  },
+						{132,112,255  },
+						{65,105,225   },
+						{85,107,47    },
+						{107,142,35   },
+						{205,92,92    },
+						{160,82,45    },
+						{178,34,34    },
+						{255,69,0     },
+						{176,48,96    },
+						{160,32,240   },
+						{139,137,137  },
+						{0,139,139    },
+						{139,0,0      },
+						{139,0,139    },
+						{154,50,205   },
+						{238,64,0     },
+						{0,139,69     } };
+					return colors[v3::utils::random(0, sizeof(colors) / sizeof(colors[0]) - 1)];
+				}
+				//生成字体大小,位置
+				std::vector<std::tuple<int, int, int>> generate_font_size() {
+					std::vector<std::tuple<int, int, int>> result;
+					int s_width = _Width / _Length;
+					int s_height = _Height;
+					for (int i = 0; i < _Length; ++i) {
+						int x = 0, y = 0, s = 0;
+						double font_centre_pos = 0.0;
+						if (s_width > s_height) {
+							s = v3::utils::random(double(s_height) - double(s_height) * 0.2, double(s_height) * 1.2);
+						}
+						else {
+							s = v3::utils::random(double(s_width) - double(s_width) * 0.2, double(s_width) * 1.2);
+						}
+						font_centre_pos = double(s) * 0.8;
+						x = v3::utils::random(0, double(s_width) - font_centre_pos);
+						y = v3::utils::random(0, double(s_height) - font_centre_pos);
+						result.push_back(std::make_tuple(s, x, y));
+					}
+					return result;
+				}
+				//验证码图片
+				std::vector<std::uint8_t> generate_captcha_image(std::string const& code) {
+					std::vector<std::uint8_t> result;
+					cimg_library::CImg<unsigned char> image(_Width, _Height, 1, 3, 255);  // 创建一个白色背景的图像
+					int s_width = _Width / _Length;
+					int s_height = _Height;
+					std::vector<std::tuple<int, int, int>> font_info = generate_font_size();
+					char c[2] = { 0 };
+					//绘制验证码
+					for (int i = 0; i < _Length; ++i) {
+						c[0] = code[i];
+						image.draw_text(i * s_width + std::get<1>(font_info[i]), std::get<2>(font_info[i]), c, generate_random_color(), 0, 1, std::get<0>(font_info[i])).width();
+					}
+					//绘制干扰线
+					for (int i = 0; i < _Line; ++i) {
+						int x1 = std::rand() % _Width;
+						int y1 = std::rand() % _Height;
+						int x2 = std::rand() % _Width;
+						int y2 = std::rand() % _Height;
+						// 生成随机颜色
+						image.draw_line(x1, y1, x2, y2, generate_random_color());
+					}
+					//绘制干扰点
+					for (int i = 0; i < _Spot; ++i) {
+						int x = std::rand() % _Width;
+						int y = std::rand() % _Height;
+						// 生成随机颜色
+						image.draw_point(x, y, generate_random_color());
+					}
+
+					//扭曲图像
+					cimg_library::CImg<unsigned char> distorted_image(_Width, _Height, 1, 3, 255);
+					cimg_forXY(image, xx, yy) {
+						int new_xx = xx + static_cast<int>(1.32 * sin(2 * 3.14 * yy * 0.045));
+						int new_yy = yy + static_cast<int>(1.42 * sin(2 * 3.14 * xx * 0.062));
+						if (new_xx >= 0 && new_xx < _Width && new_yy >= 0 && new_yy < _Height) {
+							distorted_image(xx, yy, 0, 0) = image(new_xx, new_yy, 0, 0);
+							distorted_image(xx, yy, 0, 1) = image(new_xx, new_yy, 0, 1);
+							distorted_image(xx, yy, 0, 2) = image(new_xx, new_yy, 0, 2);
+						}
+					}
+					CImage(distorted_image).save_memory_bmp(result);
+					return result;
+				}
+			private:
+				std::string session_key_;
+			};
+
+			class http_server_t {
+			public:
+				http_server_t() {
+					server_.bind<http::verb::post, http::verb::get>(std::string("/*"), &http_server_t::on_base_request, this);
+				}
+				bool start(std::string const& ip, int port) {
+					return server_.start(ip, port);
+				}
+				void stop() {
+					server_.stop();
+				}
+				void set_root_directory(std::filesystem::path const& path) {
+					server_.set_root_directory(path);
+				}
+			protected:
+				virtual void on_request(http::web_request& req, http::web_response& rep) = 0;
+			private:
+				void on_base_request(std::shared_ptr<asio2::http_session>& session_ptr, http::web_request& req, http::web_response& rep) {
+					on_request(req, rep);
+				}
+			private:
+				asio2::http_server server_;
+			};
+
+			class https_server_t {
+			public:
+				https_server_t() {
+					server_.bind<http::verb::post, http::verb::get>("/*", &https_server_t::on_base_request, this);
+				}
+				bool start(std::string const& ip, int port) {
+					return server_.start(ip, port);
+				}
+				void stop() {
+					server_.stop();
+				}
+				void set_root_directory(std::filesystem::path const& path) {
+					server_.set_root_directory(path);
+				}
+				void set_cert_file(std::string const& ca_cert_file, std::string const& private_cert_file, std::string const& private_key_file, std::string const& private_password) {
+					server_.set_cert_file(ca_cert_file, private_cert_file, private_key_file, private_password);
+				}
+			protected:
+				virtual void on_request(http::web_request& req, http::web_response& rep) = 0;
+			private:
+				void on_base_request(std::shared_ptr<asio2::https_session>& session_ptr, http::web_request& req, http::web_response& rep) {
+					on_request(req, rep);
+				}
+			private:
+				asio2::https_server server_;
+			};
+
+			template<typename _Before, typename _Err, typename _After, typename _TypeBase>
+			class http_server_base : public _TypeBase {
+			public:
+				http_server_base() :
+					_TypeBase() {
+				}
+			private:
+				virtual void on_request(http::web_request& req, http::web_response& rep)override {
+					http_context_gc http_context(req, rep);
+					try {
+						req.insert("http_route", std::string(req.path()).substr(1));
+						std::shared_ptr<controller> controller = v3::mvc::ico_controller::resolve(req);
+						std::string key(req.find("http_route_key")->value());
+						http_context::current()->set_controller_action((bool)controller ? controller->actions[key] : nullptr);
+						if (before_.before((bool)controller ? controller->actions[key] : nullptr, req, rep)) {
+							rttr::variant variant = controller->invoke(req);
+							if (variant.is_valid()) {
+								auto response = variant.get_value<web_base_response>();
+								response.set_version();
+								response.set_server();
+								response.chunked(true);
+								response.prepare_payload();
+							}
+						}
+						//文件
+						else {
+							rep.fill_file(req.path());
+							rep.set(http::field::cache_control, "max-age=31536000");
+							rep.chunked(true);
+						}
+					}
+					catch (unknown_response const&) {
+					}
+					catch (jump_response const&) {
+					}
+					catch (text_response const&) {
+					}
+					catch (html_response const&) {
+					}
+					catch (file_response const&) {
+					}
+					catch (json_response const&) {
+					}
+					catch (std::exception const& ec) {
+						err_.error(ec.what(), req, rep);
+					}
+					catch (...) {
+						err_.error("未知异常", req, rep);
+					}
+					after_.after(req, rep);
+				}
+			private:
+				_Before	before_;
+				_Err	err_;
+				_After	after_;
+			};
+
+			template<typename _Before, typename _Err, typename _After>
+			using http_server = http_server_base<_Before, _Err, _After, http_server_t>;
+
+			template<typename _Before, typename _Err, typename _After>
+			using https_server = http_server_base<_Before, _Err, _After, https_server_t>;
+		}
+	}
+}