add case-edit-module
This commit is contained in:
@@ -9,6 +9,9 @@ sys.path.insert(0, BASE_DIR)
|
||||
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
|
||||
sys.path.insert(0, os.path.join(BASE_DIR, 'extra_apps'))
|
||||
|
||||
# 此程序的请求URL
|
||||
REQUEST_HOST = 'http://127.0.0.1:8000'
|
||||
|
||||
# 此密钥将会在REST-Framework-JWT中作为JWT_SECRET_KEY
|
||||
SECRET_KEY = 'y0vj*z2@3@53nht9t!hn4jac*$6oufv+w24r65*4vom1a^2cca'
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ from rest_framework.routers import DefaultRouter
|
||||
from rest_framework.authtoken import views
|
||||
from rest_framework_jwt.views import obtain_jwt_token
|
||||
from cases.views import CasesListViewSet, CategoryViewset, HotSearchsViewset, BannerViewset
|
||||
from cases.views import IndexCategoryViewset
|
||||
from users.views import SmsCodeViewset, UserViewset, PictureCodeView
|
||||
from user_operation.views import UserFavViewset, LeavingMessageViewset
|
||||
from user_operation.views import UserFavViewset
|
||||
from django.views.generic import TemplateView
|
||||
from utils.file_views import UploadFileView
|
||||
|
||||
router = DefaultRouter() # 利用了ViewSet的重载as_view()方法进行请求方法和处理函数的动态绑定(简单好用,只需要逐一register,然后urls函数即可)
|
||||
router.register(r'cases', CasesListViewSet, base_name="cases") # 案例列表的相关操作
|
||||
@@ -22,11 +22,10 @@ router.register(r'smscodes', SmsCodeViewset, base_name="smscodes") # 短信
|
||||
router.register(r'hotsearchs', HotSearchsViewset, base_name="hotsearchs") # 热搜案例的相关操作
|
||||
router.register(r'users', UserViewset, base_name="users") # 用户的相关操作
|
||||
router.register(r'userfavs', UserFavViewset, base_name="userfavs") # 用户收藏的相关操作
|
||||
router.register(r'messages', LeavingMessageViewset, base_name="messages") # 用户留言的相关操作
|
||||
router.register(r'banners', BannerViewset, base_name="banners") # 轮播图的相关操作
|
||||
router.register(r'indexcases', IndexCategoryViewset, base_name="indexcases") # 首页案例的相关操作
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^uploadfile/(.+)/$', UploadFileView.as_view()), # 上传文件接口
|
||||
url(r'^picturecodes/', PictureCodeView.as_view(), name='picturecodes'), # 获取验证码图片
|
||||
url(r'^', include(router.urls)), # 将调用刚才注册到router的各个ViewSet的as_view()方法,得到最终的URL映射配置
|
||||
url(r'^xadmin/', xadmin.site.urls), # 注册xadmin后台管理平台的URL处理函数
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
# BootStrap笔记
|
||||
|
||||
## 1.响应式分界点
|
||||
|
||||
①xs:<576px,Extra small(portrait phones)
|
||||
|
||||
②sm:576px--768px,Small(landscape phones)
|
||||
|
||||
③md:768px--992px,Medium(tablets)
|
||||
|
||||
④lg:992px--1200px,Large(desktops)
|
||||
|
||||
⑤xl:>1200px,Extra large(large desktops)
|
||||
|
||||
实现方式为:
|
||||
|
||||
```
|
||||
media (min-width: 576px) { ... }
|
||||
```
|
||||
|
||||
或者
|
||||
|
||||
```
|
||||
include media-breakpoint-up(sm) { ... }
|
||||
```
|
||||
|
||||
即基于宽度的最小值,意味着它们应用到某一等级以及该等级之上的所有等级(比如:`.col-sm-4`应用到小、中、大、特大设备)
|
||||
@@ -1,22 +1,33 @@
|
||||
<!doctype html>
|
||||
<html class="no-js" lang="zh-CN">
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta charset="utf-8">
|
||||
<!-- 在IE运行最新的渲染模式 -->
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<!-- 初始化移动浏览显示 -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>APP Inventor案例库网站</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/foundation-icons.min.css"/>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/css/foundation.min.css"/>
|
||||
|
||||
<!-- 加载最新版本的字体图标库font-awesome -->
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app" v-cloak>
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
|
||||
<!-- Bootstrap依赖于jQuery -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/what-input/5.0.3/what-input.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/js/foundation.min.js"></script>
|
||||
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
|
||||
<!-- 基于Bootstrap3的HTML5表单验证库 -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/1000hz-bootstrap-validator/0.11.9/validator.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>APP Inventor案例库网站</title>
|
||||
|
||||
<!-- 加载最新版本的字体图标库font-awesome -->
|
||||
<link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
|
||||
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
||||
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
|
||||
.menu-fancy li {
|
||||
position: relative;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.menu-fancy li a {
|
||||
padding: 0.5rem 0;
|
||||
color: #8a8a8a;
|
||||
}
|
||||
|
||||
.menu-fancy li:after,
|
||||
.menu-fancy li:before,
|
||||
.menu-fancy a:before,
|
||||
.menu-fancy a:after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.menu-fancy li:after,
|
||||
.menu-fancy li:before {
|
||||
bottom: -4px;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
.menu-fancy li:not(.is-selected):before {
|
||||
left: 0;
|
||||
right: -2px;
|
||||
}
|
||||
|
||||
.menu-fancy li.is-selected:after {
|
||||
left: 0;
|
||||
right: 39px;
|
||||
}
|
||||
|
||||
.menu-fancy li.is-selected:before {
|
||||
right: -2px;
|
||||
width: 13px;
|
||||
}
|
||||
|
||||
.menu-fancy .is-selected a:before {
|
||||
height: 22px;
|
||||
width: 4px;
|
||||
bottom: -22px;
|
||||
right: 7px;
|
||||
}
|
||||
|
||||
.menu-fancy .is-selected a:after {
|
||||
height: 4px;
|
||||
width: 40px;
|
||||
bottom: -13px;
|
||||
right: 5px;
|
||||
-webkit-transform: rotate(30deg);
|
||||
-ms-transform: rotate(30deg);
|
||||
transform: rotate(30deg);
|
||||
}
|
||||
|
||||
.menu-fancy .menu-fancy-option1 a:hover {
|
||||
color: #3adb76;
|
||||
}
|
||||
|
||||
.menu-fancy .menu-fancy-option1:after,
|
||||
.menu-fancy .menu-fancy-option1:before,
|
||||
.menu-fancy .menu-fancy-option1 a:after,
|
||||
.menu-fancy .menu-fancy-option1 a:before {
|
||||
background-color: #3adb76;
|
||||
}
|
||||
|
||||
.menu-fancy .menu-fancy-option2 a:hover {
|
||||
color: #cc4b37;
|
||||
}
|
||||
|
||||
.menu-fancy .menu-fancy-option2:after,
|
||||
.menu-fancy .menu-fancy-option2:before,
|
||||
.menu-fancy .menu-fancy-option2 a:after,
|
||||
.menu-fancy .menu-fancy-option2 a:before {
|
||||
background-color: #cc4b37;
|
||||
}
|
||||
|
||||
.menu-fancy .menu-fancy-option3 a:hover {
|
||||
color: #1779ba;
|
||||
}
|
||||
|
||||
.menu-fancy .menu-fancy-option3:after,
|
||||
.menu-fancy .menu-fancy-option3:before,
|
||||
.menu-fancy .menu-fancy-option3 a:after,
|
||||
.menu-fancy .menu-fancy-option3 a:before {
|
||||
background-color: #1779ba;
|
||||
}
|
||||
|
||||
.menu-fancy .menu-fancy-option4 a:hover {
|
||||
color: #ffae00;
|
||||
}
|
||||
|
||||
.menu-fancy .menu-fancy-option4:after,
|
||||
.menu-fancy .menu-fancy-option4:before,
|
||||
.menu-fancy .menu-fancy-option4 a:after,
|
||||
.menu-fancy .menu-fancy-option4 a:before {
|
||||
background-color: #ffae00;
|
||||
}
|
||||
|
||||
@@ -7,26 +7,18 @@
|
||||
<!-- 初始化移动浏览显示 -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>APP Inventor案例库网站</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/foundation-icons.min.css"/>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/css/foundation.min.css"/>
|
||||
<link rel="stylesheet" href="./index_foundation.css"/>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/motion-ui/1.2.3/motion-ui.min.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<ul class="menu menu-fancy">
|
||||
<li class="menu-fancy-option1 is-selected"><a href="#">About Me</a></li>
|
||||
<li class="menu-fancy-option2"><a href="#">Work</a></li>
|
||||
<li class="menu-fancy-option3"><a href="#">Resume</a></li>
|
||||
<li class="menu-fancy-option4"><a href="#">Contact</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
<div id="app" v-cloak>
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/what-input/5.0.3/what-input.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/motion-ui/1.2.3/motion-ui.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/js/foundation.min.js"></script>
|
||||
<script>
|
||||
$(document).foundation();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
var str = '令错误';
|
||||
var index = str.indexOf('令牌');
|
||||
console.log(index);
|
||||
@@ -33,6 +33,8 @@
|
||||
"babel-preset-env": "^1.2.1",
|
||||
"babel-preset-stage-2": "^6.22.0",
|
||||
"babel-register": "^6.22.0",
|
||||
"bootstrap": "^4.0.0-beta.2",
|
||||
"bootstrap-validator": "^0.11.9",
|
||||
"chalk": "^1.1.3",
|
||||
"connect-history-api-fallback": "^1.1.0",
|
||||
"css-loader": "^0.27.3",
|
||||
|
||||
+8374
File diff suppressed because it is too large
Load Diff
@@ -1,594 +0,0 @@
|
||||
/*
|
||||
* Foundation Icons v 3.0
|
||||
* Made by ZURB 2013 http://zurb.com/playground/foundation-icon-fonts-3
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
@font-face {
|
||||
font-family: "foundation-icons";
|
||||
src: url("foundation-icons.eot");
|
||||
src: url("foundation-icons.eot?#iefix") format("embedded-opentype"),
|
||||
url("foundation-icons.woff") format("woff"),
|
||||
url("foundation-icons.ttf") format("truetype"),
|
||||
url("foundation-icons.svg#fontcustom") format("svg");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.fi-address-book:before,
|
||||
.fi-alert:before,
|
||||
.fi-align-center:before,
|
||||
.fi-align-justify:before,
|
||||
.fi-align-left:before,
|
||||
.fi-align-right:before,
|
||||
.fi-anchor:before,
|
||||
.fi-annotate:before,
|
||||
.fi-archive:before,
|
||||
.fi-arrow-down:before,
|
||||
.fi-arrow-left:before,
|
||||
.fi-arrow-right:before,
|
||||
.fi-arrow-up:before,
|
||||
.fi-arrows-compress:before,
|
||||
.fi-arrows-expand:before,
|
||||
.fi-arrows-in:before,
|
||||
.fi-arrows-out:before,
|
||||
.fi-asl:before,
|
||||
.fi-asterisk:before,
|
||||
.fi-at-sign:before,
|
||||
.fi-background-color:before,
|
||||
.fi-battery-empty:before,
|
||||
.fi-battery-full:before,
|
||||
.fi-battery-half:before,
|
||||
.fi-bitcoin-circle:before,
|
||||
.fi-bitcoin:before,
|
||||
.fi-blind:before,
|
||||
.fi-bluetooth:before,
|
||||
.fi-bold:before,
|
||||
.fi-book-bookmark:before,
|
||||
.fi-book:before,
|
||||
.fi-bookmark:before,
|
||||
.fi-braille:before,
|
||||
.fi-burst-new:before,
|
||||
.fi-burst-sale:before,
|
||||
.fi-burst:before,
|
||||
.fi-calendar:before,
|
||||
.fi-camera:before,
|
||||
.fi-check:before,
|
||||
.fi-checkbox:before,
|
||||
.fi-clipboard-notes:before,
|
||||
.fi-clipboard-pencil:before,
|
||||
.fi-clipboard:before,
|
||||
.fi-clock:before,
|
||||
.fi-closed-caption:before,
|
||||
.fi-cloud:before,
|
||||
.fi-comment-minus:before,
|
||||
.fi-comment-quotes:before,
|
||||
.fi-comment-video:before,
|
||||
.fi-comment:before,
|
||||
.fi-comments:before,
|
||||
.fi-compass:before,
|
||||
.fi-contrast:before,
|
||||
.fi-credit-card:before,
|
||||
.fi-crop:before,
|
||||
.fi-crown:before,
|
||||
.fi-css3:before,
|
||||
.fi-database:before,
|
||||
.fi-die-five:before,
|
||||
.fi-die-four:before,
|
||||
.fi-die-one:before,
|
||||
.fi-die-six:before,
|
||||
.fi-die-three:before,
|
||||
.fi-die-two:before,
|
||||
.fi-dislike:before,
|
||||
.fi-dollar-bill:before,
|
||||
.fi-dollar:before,
|
||||
.fi-download:before,
|
||||
.fi-eject:before,
|
||||
.fi-elevator:before,
|
||||
.fi-euro:before,
|
||||
.fi-eye:before,
|
||||
.fi-fast-forward:before,
|
||||
.fi-female-symbol:before,
|
||||
.fi-female:before,
|
||||
.fi-filter:before,
|
||||
.fi-first-aid:before,
|
||||
.fi-flag:before,
|
||||
.fi-folder-add:before,
|
||||
.fi-folder-lock:before,
|
||||
.fi-folder:before,
|
||||
.fi-foot:before,
|
||||
.fi-foundation:before,
|
||||
.fi-graph-bar:before,
|
||||
.fi-graph-horizontal:before,
|
||||
.fi-graph-pie:before,
|
||||
.fi-graph-trend:before,
|
||||
.fi-guide-dog:before,
|
||||
.fi-hearing-aid:before,
|
||||
.fi-heart:before,
|
||||
.fi-home:before,
|
||||
.fi-html5:before,
|
||||
.fi-indent-less:before,
|
||||
.fi-indent-more:before,
|
||||
.fi-info:before,
|
||||
.fi-italic:before,
|
||||
.fi-key:before,
|
||||
.fi-laptop:before,
|
||||
.fi-layout:before,
|
||||
.fi-lightbulb:before,
|
||||
.fi-like:before,
|
||||
.fi-link:before,
|
||||
.fi-list-bullet:before,
|
||||
.fi-list-number:before,
|
||||
.fi-list-thumbnails:before,
|
||||
.fi-list:before,
|
||||
.fi-lock:before,
|
||||
.fi-loop:before,
|
||||
.fi-magnifying-glass:before,
|
||||
.fi-mail:before,
|
||||
.fi-male-female:before,
|
||||
.fi-male-symbol:before,
|
||||
.fi-male:before,
|
||||
.fi-map:before,
|
||||
.fi-marker:before,
|
||||
.fi-megaphone:before,
|
||||
.fi-microphone:before,
|
||||
.fi-minus-circle:before,
|
||||
.fi-minus:before,
|
||||
.fi-mobile-signal:before,
|
||||
.fi-mobile:before,
|
||||
.fi-monitor:before,
|
||||
.fi-mountains:before,
|
||||
.fi-music:before,
|
||||
.fi-next:before,
|
||||
.fi-no-dogs:before,
|
||||
.fi-no-smoking:before,
|
||||
.fi-page-add:before,
|
||||
.fi-page-copy:before,
|
||||
.fi-page-csv:before,
|
||||
.fi-page-delete:before,
|
||||
.fi-page-doc:before,
|
||||
.fi-page-edit:before,
|
||||
.fi-page-export-csv:before,
|
||||
.fi-page-export-doc:before,
|
||||
.fi-page-export-pdf:before,
|
||||
.fi-page-export:before,
|
||||
.fi-page-filled:before,
|
||||
.fi-page-multiple:before,
|
||||
.fi-page-pdf:before,
|
||||
.fi-page-remove:before,
|
||||
.fi-page-search:before,
|
||||
.fi-page:before,
|
||||
.fi-paint-bucket:before,
|
||||
.fi-paperclip:before,
|
||||
.fi-pause:before,
|
||||
.fi-paw:before,
|
||||
.fi-paypal:before,
|
||||
.fi-pencil:before,
|
||||
.fi-photo:before,
|
||||
.fi-play-circle:before,
|
||||
.fi-play-video:before,
|
||||
.fi-play:before,
|
||||
.fi-plus:before,
|
||||
.fi-pound:before,
|
||||
.fi-power:before,
|
||||
.fi-previous:before,
|
||||
.fi-price-tag:before,
|
||||
.fi-pricetag-multiple:before,
|
||||
.fi-print:before,
|
||||
.fi-prohibited:before,
|
||||
.fi-projection-screen:before,
|
||||
.fi-puzzle:before,
|
||||
.fi-quote:before,
|
||||
.fi-record:before,
|
||||
.fi-refresh:before,
|
||||
.fi-results-demographics:before,
|
||||
.fi-results:before,
|
||||
.fi-rewind-ten:before,
|
||||
.fi-rewind:before,
|
||||
.fi-rss:before,
|
||||
.fi-safety-cone:before,
|
||||
.fi-save:before,
|
||||
.fi-share:before,
|
||||
.fi-sheriff-badge:before,
|
||||
.fi-shield:before,
|
||||
.fi-shopping-bag:before,
|
||||
.fi-shopping-cart:before,
|
||||
.fi-shuffle:before,
|
||||
.fi-skull:before,
|
||||
.fi-social-500px:before,
|
||||
.fi-social-adobe:before,
|
||||
.fi-social-amazon:before,
|
||||
.fi-social-android:before,
|
||||
.fi-social-apple:before,
|
||||
.fi-social-behance:before,
|
||||
.fi-social-bing:before,
|
||||
.fi-social-blogger:before,
|
||||
.fi-social-delicious:before,
|
||||
.fi-social-designer-news:before,
|
||||
.fi-social-deviant-art:before,
|
||||
.fi-social-digg:before,
|
||||
.fi-social-dribbble:before,
|
||||
.fi-social-drive:before,
|
||||
.fi-social-dropbox:before,
|
||||
.fi-social-evernote:before,
|
||||
.fi-social-facebook:before,
|
||||
.fi-social-flickr:before,
|
||||
.fi-social-forrst:before,
|
||||
.fi-social-foursquare:before,
|
||||
.fi-social-game-center:before,
|
||||
.fi-social-github:before,
|
||||
.fi-social-google-plus:before,
|
||||
.fi-social-hacker-news:before,
|
||||
.fi-social-hi5:before,
|
||||
.fi-social-instagram:before,
|
||||
.fi-social-joomla:before,
|
||||
.fi-social-lastfm:before,
|
||||
.fi-social-linkedin:before,
|
||||
.fi-social-medium:before,
|
||||
.fi-social-myspace:before,
|
||||
.fi-social-orkut:before,
|
||||
.fi-social-path:before,
|
||||
.fi-social-picasa:before,
|
||||
.fi-social-pinterest:before,
|
||||
.fi-social-rdio:before,
|
||||
.fi-social-reddit:before,
|
||||
.fi-social-skillshare:before,
|
||||
.fi-social-skype:before,
|
||||
.fi-social-smashing-mag:before,
|
||||
.fi-social-snapchat:before,
|
||||
.fi-social-spotify:before,
|
||||
.fi-social-squidoo:before,
|
||||
.fi-social-stack-overflow:before,
|
||||
.fi-social-steam:before,
|
||||
.fi-social-stumbleupon:before,
|
||||
.fi-social-treehouse:before,
|
||||
.fi-social-tumblr:before,
|
||||
.fi-social-twitter:before,
|
||||
.fi-social-vimeo:before,
|
||||
.fi-social-windows:before,
|
||||
.fi-social-xbox:before,
|
||||
.fi-social-yahoo:before,
|
||||
.fi-social-yelp:before,
|
||||
.fi-social-youtube:before,
|
||||
.fi-social-zerply:before,
|
||||
.fi-social-zurb:before,
|
||||
.fi-sound:before,
|
||||
.fi-star:before,
|
||||
.fi-stop:before,
|
||||
.fi-strikethrough:before,
|
||||
.fi-subscript:before,
|
||||
.fi-superscript:before,
|
||||
.fi-tablet-landscape:before,
|
||||
.fi-tablet-portrait:before,
|
||||
.fi-target-two:before,
|
||||
.fi-target:before,
|
||||
.fi-telephone-accessible:before,
|
||||
.fi-telephone:before,
|
||||
.fi-text-color:before,
|
||||
.fi-thumbnails:before,
|
||||
.fi-ticket:before,
|
||||
.fi-torso-business:before,
|
||||
.fi-torso-female:before,
|
||||
.fi-torso:before,
|
||||
.fi-torsos-all-female:before,
|
||||
.fi-torsos-all:before,
|
||||
.fi-torsos-female-male:before,
|
||||
.fi-torsos-male-female:before,
|
||||
.fi-torsos:before,
|
||||
.fi-trash:before,
|
||||
.fi-trees:before,
|
||||
.fi-trophy:before,
|
||||
.fi-underline:before,
|
||||
.fi-universal-access:before,
|
||||
.fi-unlink:before,
|
||||
.fi-unlock:before,
|
||||
.fi-upload-cloud:before,
|
||||
.fi-upload:before,
|
||||
.fi-usb:before,
|
||||
.fi-video:before,
|
||||
.fi-volume-none:before,
|
||||
.fi-volume-strike:before,
|
||||
.fi-volume:before,
|
||||
.fi-web:before,
|
||||
.fi-wheelchair:before,
|
||||
.fi-widget:before,
|
||||
.fi-wrench:before,
|
||||
.fi-x-circle:before,
|
||||
.fi-x:before,
|
||||
.fi-yen:before,
|
||||
.fi-zoom-in:before,
|
||||
.fi-zoom-out:before {
|
||||
font-family: "foundation-icons";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
display: inline-block;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.fi-address-book:before { content: "\f100"; }
|
||||
.fi-alert:before { content: "\f101"; }
|
||||
.fi-align-center:before { content: "\f102"; }
|
||||
.fi-align-justify:before { content: "\f103"; }
|
||||
.fi-align-left:before { content: "\f104"; }
|
||||
.fi-align-right:before { content: "\f105"; }
|
||||
.fi-anchor:before { content: "\f106"; }
|
||||
.fi-annotate:before { content: "\f107"; }
|
||||
.fi-archive:before { content: "\f108"; }
|
||||
.fi-arrow-down:before { content: "\f109"; }
|
||||
.fi-arrow-left:before { content: "\f10a"; }
|
||||
.fi-arrow-right:before { content: "\f10b"; }
|
||||
.fi-arrow-up:before { content: "\f10c"; }
|
||||
.fi-arrows-compress:before { content: "\f10d"; }
|
||||
.fi-arrows-expand:before { content: "\f10e"; }
|
||||
.fi-arrows-in:before { content: "\f10f"; }
|
||||
.fi-arrows-out:before { content: "\f110"; }
|
||||
.fi-asl:before { content: "\f111"; }
|
||||
.fi-asterisk:before { content: "\f112"; }
|
||||
.fi-at-sign:before { content: "\f113"; }
|
||||
.fi-background-color:before { content: "\f114"; }
|
||||
.fi-battery-empty:before { content: "\f115"; }
|
||||
.fi-battery-full:before { content: "\f116"; }
|
||||
.fi-battery-half:before { content: "\f117"; }
|
||||
.fi-bitcoin-circle:before { content: "\f118"; }
|
||||
.fi-bitcoin:before { content: "\f119"; }
|
||||
.fi-blind:before { content: "\f11a"; }
|
||||
.fi-bluetooth:before { content: "\f11b"; }
|
||||
.fi-bold:before { content: "\f11c"; }
|
||||
.fi-book-bookmark:before { content: "\f11d"; }
|
||||
.fi-book:before { content: "\f11e"; }
|
||||
.fi-bookmark:before { content: "\f11f"; }
|
||||
.fi-braille:before { content: "\f120"; }
|
||||
.fi-burst-new:before { content: "\f121"; }
|
||||
.fi-burst-sale:before { content: "\f122"; }
|
||||
.fi-burst:before { content: "\f123"; }
|
||||
.fi-calendar:before { content: "\f124"; }
|
||||
.fi-camera:before { content: "\f125"; }
|
||||
.fi-check:before { content: "\f126"; }
|
||||
.fi-checkbox:before { content: "\f127"; }
|
||||
.fi-clipboard-notes:before { content: "\f128"; }
|
||||
.fi-clipboard-pencil:before { content: "\f129"; }
|
||||
.fi-clipboard:before { content: "\f12a"; }
|
||||
.fi-clock:before { content: "\f12b"; }
|
||||
.fi-closed-caption:before { content: "\f12c"; }
|
||||
.fi-cloud:before { content: "\f12d"; }
|
||||
.fi-comment-minus:before { content: "\f12e"; }
|
||||
.fi-comment-quotes:before { content: "\f12f"; }
|
||||
.fi-comment-video:before { content: "\f130"; }
|
||||
.fi-comment:before { content: "\f131"; }
|
||||
.fi-comments:before { content: "\f132"; }
|
||||
.fi-compass:before { content: "\f133"; }
|
||||
.fi-contrast:before { content: "\f134"; }
|
||||
.fi-credit-card:before { content: "\f135"; }
|
||||
.fi-crop:before { content: "\f136"; }
|
||||
.fi-crown:before { content: "\f137"; }
|
||||
.fi-css3:before { content: "\f138"; }
|
||||
.fi-database:before { content: "\f139"; }
|
||||
.fi-die-five:before { content: "\f13a"; }
|
||||
.fi-die-four:before { content: "\f13b"; }
|
||||
.fi-die-one:before { content: "\f13c"; }
|
||||
.fi-die-six:before { content: "\f13d"; }
|
||||
.fi-die-three:before { content: "\f13e"; }
|
||||
.fi-die-two:before { content: "\f13f"; }
|
||||
.fi-dislike:before { content: "\f140"; }
|
||||
.fi-dollar-bill:before { content: "\f141"; }
|
||||
.fi-dollar:before { content: "\f142"; }
|
||||
.fi-download:before { content: "\f143"; }
|
||||
.fi-eject:before { content: "\f144"; }
|
||||
.fi-elevator:before { content: "\f145"; }
|
||||
.fi-euro:before { content: "\f146"; }
|
||||
.fi-eye:before { content: "\f147"; }
|
||||
.fi-fast-forward:before { content: "\f148"; }
|
||||
.fi-female-symbol:before { content: "\f149"; }
|
||||
.fi-female:before { content: "\f14a"; }
|
||||
.fi-filter:before { content: "\f14b"; }
|
||||
.fi-first-aid:before { content: "\f14c"; }
|
||||
.fi-flag:before { content: "\f14d"; }
|
||||
.fi-folder-add:before { content: "\f14e"; }
|
||||
.fi-folder-lock:before { content: "\f14f"; }
|
||||
.fi-folder:before { content: "\f150"; }
|
||||
.fi-foot:before { content: "\f151"; }
|
||||
.fi-foundation:before { content: "\f152"; }
|
||||
.fi-graph-bar:before { content: "\f153"; }
|
||||
.fi-graph-horizontal:before { content: "\f154"; }
|
||||
.fi-graph-pie:before { content: "\f155"; }
|
||||
.fi-graph-trend:before { content: "\f156"; }
|
||||
.fi-guide-dog:before { content: "\f157"; }
|
||||
.fi-hearing-aid:before { content: "\f158"; }
|
||||
.fi-heart:before { content: "\f159"; }
|
||||
.fi-home:before { content: "\f15a"; }
|
||||
.fi-html5:before { content: "\f15b"; }
|
||||
.fi-indent-less:before { content: "\f15c"; }
|
||||
.fi-indent-more:before { content: "\f15d"; }
|
||||
.fi-info:before { content: "\f15e"; }
|
||||
.fi-italic:before { content: "\f15f"; }
|
||||
.fi-key:before { content: "\f160"; }
|
||||
.fi-laptop:before { content: "\f161"; }
|
||||
.fi-layout:before { content: "\f162"; }
|
||||
.fi-lightbulb:before { content: "\f163"; }
|
||||
.fi-like:before { content: "\f164"; }
|
||||
.fi-link:before { content: "\f165"; }
|
||||
.fi-list-bullet:before { content: "\f166"; }
|
||||
.fi-list-number:before { content: "\f167"; }
|
||||
.fi-list-thumbnails:before { content: "\f168"; }
|
||||
.fi-list:before { content: "\f169"; }
|
||||
.fi-lock:before { content: "\f16a"; }
|
||||
.fi-loop:before { content: "\f16b"; }
|
||||
.fi-magnifying-glass:before { content: "\f16c"; }
|
||||
.fi-mail:before { content: "\f16d"; }
|
||||
.fi-male-female:before { content: "\f16e"; }
|
||||
.fi-male-symbol:before { content: "\f16f"; }
|
||||
.fi-male:before { content: "\f170"; }
|
||||
.fi-map:before { content: "\f171"; }
|
||||
.fi-marker:before { content: "\f172"; }
|
||||
.fi-megaphone:before { content: "\f173"; }
|
||||
.fi-microphone:before { content: "\f174"; }
|
||||
.fi-minus-circle:before { content: "\f175"; }
|
||||
.fi-minus:before { content: "\f176"; }
|
||||
.fi-mobile-signal:before { content: "\f177"; }
|
||||
.fi-mobile:before { content: "\f178"; }
|
||||
.fi-monitor:before { content: "\f179"; }
|
||||
.fi-mountains:before { content: "\f17a"; }
|
||||
.fi-music:before { content: "\f17b"; }
|
||||
.fi-next:before { content: "\f17c"; }
|
||||
.fi-no-dogs:before { content: "\f17d"; }
|
||||
.fi-no-smoking:before { content: "\f17e"; }
|
||||
.fi-page-add:before { content: "\f17f"; }
|
||||
.fi-page-copy:before { content: "\f180"; }
|
||||
.fi-page-csv:before { content: "\f181"; }
|
||||
.fi-page-delete:before { content: "\f182"; }
|
||||
.fi-page-doc:before { content: "\f183"; }
|
||||
.fi-page-edit:before { content: "\f184"; }
|
||||
.fi-page-export-csv:before { content: "\f185"; }
|
||||
.fi-page-export-doc:before { content: "\f186"; }
|
||||
.fi-page-export-pdf:before { content: "\f187"; }
|
||||
.fi-page-export:before { content: "\f188"; }
|
||||
.fi-page-filled:before { content: "\f189"; }
|
||||
.fi-page-multiple:before { content: "\f18a"; }
|
||||
.fi-page-pdf:before { content: "\f18b"; }
|
||||
.fi-page-remove:before { content: "\f18c"; }
|
||||
.fi-page-search:before { content: "\f18d"; }
|
||||
.fi-page:before { content: "\f18e"; }
|
||||
.fi-paint-bucket:before { content: "\f18f"; }
|
||||
.fi-paperclip:before { content: "\f190"; }
|
||||
.fi-pause:before { content: "\f191"; }
|
||||
.fi-paw:before { content: "\f192"; }
|
||||
.fi-paypal:before { content: "\f193"; }
|
||||
.fi-pencil:before { content: "\f194"; }
|
||||
.fi-photo:before { content: "\f195"; }
|
||||
.fi-play-circle:before { content: "\f196"; }
|
||||
.fi-play-video:before { content: "\f197"; }
|
||||
.fi-play:before { content: "\f198"; }
|
||||
.fi-plus:before { content: "\f199"; }
|
||||
.fi-pound:before { content: "\f19a"; }
|
||||
.fi-power:before { content: "\f19b"; }
|
||||
.fi-previous:before { content: "\f19c"; }
|
||||
.fi-price-tag:before { content: "\f19d"; }
|
||||
.fi-pricetag-multiple:before { content: "\f19e"; }
|
||||
.fi-print:before { content: "\f19f"; }
|
||||
.fi-prohibited:before { content: "\f1a0"; }
|
||||
.fi-projection-screen:before { content: "\f1a1"; }
|
||||
.fi-puzzle:before { content: "\f1a2"; }
|
||||
.fi-quote:before { content: "\f1a3"; }
|
||||
.fi-record:before { content: "\f1a4"; }
|
||||
.fi-refresh:before { content: "\f1a5"; }
|
||||
.fi-results-demographics:before { content: "\f1a6"; }
|
||||
.fi-results:before { content: "\f1a7"; }
|
||||
.fi-rewind-ten:before { content: "\f1a8"; }
|
||||
.fi-rewind:before { content: "\f1a9"; }
|
||||
.fi-rss:before { content: "\f1aa"; }
|
||||
.fi-safety-cone:before { content: "\f1ab"; }
|
||||
.fi-save:before { content: "\f1ac"; }
|
||||
.fi-share:before { content: "\f1ad"; }
|
||||
.fi-sheriff-badge:before { content: "\f1ae"; }
|
||||
.fi-shield:before { content: "\f1af"; }
|
||||
.fi-shopping-bag:before { content: "\f1b0"; }
|
||||
.fi-shopping-cart:before { content: "\f1b1"; }
|
||||
.fi-shuffle:before { content: "\f1b2"; }
|
||||
.fi-skull:before { content: "\f1b3"; }
|
||||
.fi-social-500px:before { content: "\f1b4"; }
|
||||
.fi-social-adobe:before { content: "\f1b5"; }
|
||||
.fi-social-amazon:before { content: "\f1b6"; }
|
||||
.fi-social-android:before { content: "\f1b7"; }
|
||||
.fi-social-apple:before { content: "\f1b8"; }
|
||||
.fi-social-behance:before { content: "\f1b9"; }
|
||||
.fi-social-bing:before { content: "\f1ba"; }
|
||||
.fi-social-blogger:before { content: "\f1bb"; }
|
||||
.fi-social-delicious:before { content: "\f1bc"; }
|
||||
.fi-social-designer-news:before { content: "\f1bd"; }
|
||||
.fi-social-deviant-art:before { content: "\f1be"; }
|
||||
.fi-social-digg:before { content: "\f1bf"; }
|
||||
.fi-social-dribbble:before { content: "\f1c0"; }
|
||||
.fi-social-drive:before { content: "\f1c1"; }
|
||||
.fi-social-dropbox:before { content: "\f1c2"; }
|
||||
.fi-social-evernote:before { content: "\f1c3"; }
|
||||
.fi-social-facebook:before { content: "\f1c4"; }
|
||||
.fi-social-flickr:before { content: "\f1c5"; }
|
||||
.fi-social-forrst:before { content: "\f1c6"; }
|
||||
.fi-social-foursquare:before { content: "\f1c7"; }
|
||||
.fi-social-game-center:before { content: "\f1c8"; }
|
||||
.fi-social-github:before { content: "\f1c9"; }
|
||||
.fi-social-google-plus:before { content: "\f1ca"; }
|
||||
.fi-social-hacker-news:before { content: "\f1cb"; }
|
||||
.fi-social-hi5:before { content: "\f1cc"; }
|
||||
.fi-social-instagram:before { content: "\f1cd"; }
|
||||
.fi-social-joomla:before { content: "\f1ce"; }
|
||||
.fi-social-lastfm:before { content: "\f1cf"; }
|
||||
.fi-social-linkedin:before { content: "\f1d0"; }
|
||||
.fi-social-medium:before { content: "\f1d1"; }
|
||||
.fi-social-myspace:before { content: "\f1d2"; }
|
||||
.fi-social-orkut:before { content: "\f1d3"; }
|
||||
.fi-social-path:before { content: "\f1d4"; }
|
||||
.fi-social-picasa:before { content: "\f1d5"; }
|
||||
.fi-social-pinterest:before { content: "\f1d6"; }
|
||||
.fi-social-rdio:before { content: "\f1d7"; }
|
||||
.fi-social-reddit:before { content: "\f1d8"; }
|
||||
.fi-social-skillshare:before { content: "\f1d9"; }
|
||||
.fi-social-skype:before { content: "\f1da"; }
|
||||
.fi-social-smashing-mag:before { content: "\f1db"; }
|
||||
.fi-social-snapchat:before { content: "\f1dc"; }
|
||||
.fi-social-spotify:before { content: "\f1dd"; }
|
||||
.fi-social-squidoo:before { content: "\f1de"; }
|
||||
.fi-social-stack-overflow:before { content: "\f1df"; }
|
||||
.fi-social-steam:before { content: "\f1e0"; }
|
||||
.fi-social-stumbleupon:before { content: "\f1e1"; }
|
||||
.fi-social-treehouse:before { content: "\f1e2"; }
|
||||
.fi-social-tumblr:before { content: "\f1e3"; }
|
||||
.fi-social-twitter:before { content: "\f1e4"; }
|
||||
.fi-social-vimeo:before { content: "\f1e5"; }
|
||||
.fi-social-windows:before { content: "\f1e6"; }
|
||||
.fi-social-xbox:before { content: "\f1e7"; }
|
||||
.fi-social-yahoo:before { content: "\f1e8"; }
|
||||
.fi-social-yelp:before { content: "\f1e9"; }
|
||||
.fi-social-youtube:before { content: "\f1ea"; }
|
||||
.fi-social-zerply:before { content: "\f1eb"; }
|
||||
.fi-social-zurb:before { content: "\f1ec"; }
|
||||
.fi-sound:before { content: "\f1ed"; }
|
||||
.fi-star:before { content: "\f1ee"; }
|
||||
.fi-stop:before { content: "\f1ef"; }
|
||||
.fi-strikethrough:before { content: "\f1f0"; }
|
||||
.fi-subscript:before { content: "\f1f1"; }
|
||||
.fi-superscript:before { content: "\f1f2"; }
|
||||
.fi-tablet-landscape:before { content: "\f1f3"; }
|
||||
.fi-tablet-portrait:before { content: "\f1f4"; }
|
||||
.fi-target-two:before { content: "\f1f5"; }
|
||||
.fi-target:before { content: "\f1f6"; }
|
||||
.fi-telephone-accessible:before { content: "\f1f7"; }
|
||||
.fi-telephone:before { content: "\f1f8"; }
|
||||
.fi-text-color:before { content: "\f1f9"; }
|
||||
.fi-thumbnails:before { content: "\f1fa"; }
|
||||
.fi-ticket:before { content: "\f1fb"; }
|
||||
.fi-torso-business:before { content: "\f1fc"; }
|
||||
.fi-torso-female:before { content: "\f1fd"; }
|
||||
.fi-torso:before { content: "\f1fe"; }
|
||||
.fi-torsos-all-female:before { content: "\f1ff"; }
|
||||
.fi-torsos-all:before { content: "\f200"; }
|
||||
.fi-torsos-female-male:before { content: "\f201"; }
|
||||
.fi-torsos-male-female:before { content: "\f202"; }
|
||||
.fi-torsos:before { content: "\f203"; }
|
||||
.fi-trash:before { content: "\f204"; }
|
||||
.fi-trees:before { content: "\f205"; }
|
||||
.fi-trophy:before { content: "\f206"; }
|
||||
.fi-underline:before { content: "\f207"; }
|
||||
.fi-universal-access:before { content: "\f208"; }
|
||||
.fi-unlink:before { content: "\f209"; }
|
||||
.fi-unlock:before { content: "\f20a"; }
|
||||
.fi-upload-cloud:before { content: "\f20b"; }
|
||||
.fi-upload:before { content: "\f20c"; }
|
||||
.fi-usb:before { content: "\f20d"; }
|
||||
.fi-video:before { content: "\f20e"; }
|
||||
.fi-volume-none:before { content: "\f20f"; }
|
||||
.fi-volume-strike:before { content: "\f210"; }
|
||||
.fi-volume:before { content: "\f211"; }
|
||||
.fi-web:before { content: "\f212"; }
|
||||
.fi-wheelchair:before { content: "\f213"; }
|
||||
.fi-widget:before { content: "\f214"; }
|
||||
.fi-wrench:before { content: "\f215"; }
|
||||
.fi-x-circle:before { content: "\f216"; }
|
||||
.fi-x:before { content: "\f217"; }
|
||||
.fi-yen:before { content: "\f218"; }
|
||||
.fi-zoom-in:before { content: "\f219"; }
|
||||
.fi-zoom-out:before { content: "\f21a"; }
|
||||
-5805
File diff suppressed because it is too large
Load Diff
@@ -1,100 +0,0 @@
|
||||
<!doctype html>
|
||||
<html class="no-js" lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<!-- 在IE运行最新的渲染模式 -->
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<!-- 初始化移动浏览显示 -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>APP Inventor案例库网站</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundicons/3.0.0/foundation-icons.min.css"/>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/css/foundation.min.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<form data-abide novalidate>
|
||||
<div data-abide-error class="alert callout" style="display: none;">
|
||||
<p><i class="fi-alert"></i> There are some errors in your form.</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="small-12 columns">
|
||||
<label>Number Required
|
||||
<input type="text" placeholder="1234" aria-describedby="exampleHelpText" required pattern="number">
|
||||
<span class="form-error">
|
||||
Yo, you had better fill this out, it's required.
|
||||
</span>
|
||||
</label>
|
||||
<p class="help-text" id="exampleHelpText">Here's how you use this input field!</p>
|
||||
</div>
|
||||
<div class="small-12 columns">
|
||||
<label>Re-enter Password
|
||||
<input type="password" placeholder="yeti4preZ" aria-describedby="exampleHelpText2" required pattern="alpha_numeric" data-equalto="password">
|
||||
<span class="form-error">
|
||||
Hey, passwords are supposed to match!
|
||||
</span>
|
||||
</label>
|
||||
<p class="help-text" id="exampleHelpText2">This field is using the `data-equalto="password"` attribute, causing it to match the password field above.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="large-6 columns">
|
||||
<label>URL Pattern, not required, but throws error if it doesn't match the Regular Expression for a valid URL.
|
||||
<input type="text" placeholder="https://foundation.zurb.com" pattern="url">
|
||||
</label>
|
||||
</div>
|
||||
<div class="large-6 columns">
|
||||
<label>Website Pattern, not required, but throws error if it doesn't match the Regular Expression for a valid URL or a Domain.
|
||||
<input type="text" placeholder="https://zurb.com or zurb.com" pattern="website">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="large-6 columns">
|
||||
<label>European Cars, Choose One, it can't be the blank option.
|
||||
<select id="select" required>
|
||||
<option value=""></option>
|
||||
<option value="volvo">Volvo</option>
|
||||
<option value="saab">Saab</option>
|
||||
<option value="mercedes">Mercedes</option>
|
||||
<option value="audi">Audi</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<fieldset class="large-6 columns">
|
||||
<legend>Check these out</legend>
|
||||
<input id="checkbox1" type="checkbox"><label for="checkbox1">Checkbox 1</label>
|
||||
<input id="checkbox2" type="checkbox" required><label for="checkbox2">Checkbox 2</label>
|
||||
<input id="checkbox3" type="checkbox"><label for="checkbox3">Checkbox 3</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="row">
|
||||
<fieldset class="large-6 columns">
|
||||
<legend>Choose Your Favorite - not required, you can leave this one blank.</legend>
|
||||
<input type="radio" name="pockets" value="Red" id="pocketsRed"><label for="pocketsRed">Red</label>
|
||||
<input type="radio" name="pockets" value="Blue" id="pocketsBlue"><label for="pocketsBlue">Blue</label>
|
||||
<input type="radio" name="pockets" value="Yellow" id="pocketsYellow"><label for="pocketsYellow">Yellow</label>
|
||||
</fieldset>
|
||||
<fieldset class="large-6 columns">
|
||||
<legend>Choose Your Favorite, and this is required, so you have to pick one.</legend>
|
||||
<input type="radio" name="pokemon" value="Red" id="pokemonRed"><label for="pokemonRed">Red</label>
|
||||
<input type="radio" name="pokemon" value="Blue" id="pokemonBlue" required><label for="pokemonBlue">Blue</label>
|
||||
<input type="radio" name="pokemon" value="Yellow" id="pokemonYellow"><label for="pokemonYellow">Yellow</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="row">
|
||||
<fieldset class="large-6 columns">
|
||||
<button class="button" type="submit" value="Submit">Submit</button>
|
||||
</fieldset>
|
||||
<fieldset class="large-6 columns">
|
||||
<button class="button" type="reset" value="Reset">Reset</button>
|
||||
</fieldset>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/what-input/5.0.3/what-input.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/js/foundation.min.js"></script>
|
||||
<script>
|
||||
$(document).foundation();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+3850
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div class="media">
|
||||
<a class="media-left" href="#">
|
||||
<img class="media-object" v-bind:data-src="thumbnailSrc" alt="Generic placeholder image">
|
||||
</a>
|
||||
<div class="media-body">
|
||||
<h4 class="media-heading" v-text="title"></h4>
|
||||
{{content}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
// 模板<template>默认替换挂载元素,如果 replace 选项为 false,模板将插入挂载元素内
|
||||
replace: true,
|
||||
props: {
|
||||
thumbnailSrc: String,
|
||||
title: String,
|
||||
content: String
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -1,191 +0,0 @@
|
||||
<template>
|
||||
<!-- 置顶导航 -->
|
||||
<nav class="top-bar topbar-responsive">
|
||||
<div class="top-bar-title">
|
||||
<!-- data-responsive-toggle指定触发显示/消失的对象的id,如果屏幕的大小大于640px则不显示该触发按钮 -->
|
||||
<span data-responsive-toggle="topbar-responsive" data-hide-for="medium">
|
||||
<!--- 附带data-toggle属性的元素负责真正事件的触发 -->
|
||||
<button class="menu-icon" type="button" data-toggle></button>
|
||||
</span>
|
||||
<a class="topbar-responsive-logo" href="#"><strong>APP Inventor案例库</strong></a>
|
||||
</div>
|
||||
<div id="topbar-responsive" class="topbar-responsive-links">
|
||||
<div class="top-bar-right">
|
||||
<!-- Add the .simple class to a Menu to remove the padding and color change -->
|
||||
<ul class="menu simple vertical medium-horizontal">
|
||||
<li><a href="/">首页</a></li>
|
||||
<li><a href="#">案例</a></li>
|
||||
<li><a href="#">发表</a></li>
|
||||
<li><a href="#">问答</a></li>
|
||||
<li><input type="search" placeholder="Search"></li>
|
||||
<li>
|
||||
<button type="button" class="button hollow topbar-responsive-button" v-on:click='toLoginPage'>登录
|
||||
</button>
|
||||
</li>
|
||||
<li class="menu-text" style="color:gray">Or</li>
|
||||
<li>
|
||||
<button type="button" class="button hollow topbar-responsive-button" v-on:click='toRegisterPage'>注册
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import $ from 'jquery';
|
||||
|
||||
export default {
|
||||
// 模板<template>默认替换挂载元素,如果 replace 选项为 false,模板将插入挂载元素内
|
||||
replace: true,
|
||||
props: {
|
||||
pageType: String
|
||||
},
|
||||
methods: {
|
||||
toLoginPage: function () {
|
||||
this.$root.jumpToThisPage('login');
|
||||
},
|
||||
toRegisterPage: function () {
|
||||
this.$root.jumpToThisPage('register');
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this.$nextTick(function () {
|
||||
var prev = 0;
|
||||
var $window = $(window);
|
||||
var nav = $('.scrollhide-nav');
|
||||
|
||||
$window.on('scroll', function () {
|
||||
var scrollTop = $window.scrollTop();
|
||||
nav.toggleClass('hidden', scrollTop > prev);
|
||||
prev = scrollTop;
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import "../assets/scss/constant";
|
||||
@import "../../node_modules/foundation-sites/scss/util/util";
|
||||
|
||||
$topbar-responsive-bg: #2c3840;
|
||||
$topbar-responsive-animation-type: fade-in; // or use slide-down or none
|
||||
|
||||
.or-text {
|
||||
color: $White;
|
||||
}
|
||||
|
||||
.topbar-responsive {
|
||||
background: $topbar-responsive-bg;
|
||||
padding: 1rem 1.5rem;
|
||||
|
||||
// 白色字体+垂直居中
|
||||
.topbar-responsive-logo {
|
||||
color: $White;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.menu {
|
||||
background: $topbar-responsive-bg;
|
||||
|
||||
li:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $White;
|
||||
transition: color 0.15s ease-in;
|
||||
|
||||
&:hover {
|
||||
color: lighten($topbar-responsive-bg, 60%);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 39.9375em) {
|
||||
padding: 0.875rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
.topbar-responsive-button {
|
||||
color: $White;
|
||||
border-color: $White;
|
||||
// 向 div 元素添加圆角边框
|
||||
border-radius: 500px;
|
||||
// transition: property duration timing-function delay;
|
||||
// property属性规定应用过渡效果的CSS属性的名称(当指定的 CSS 属性改变时,过渡效果将开始)
|
||||
// ease-in规定以慢速开始的过渡效果
|
||||
transition: color 0.15s ease-in, border-color 0.15s ease-in;
|
||||
// 伪类嵌套和属性嵌套非常类似,只不过他需要借助`&`符号一起配合使用
|
||||
&:hover {
|
||||
color: lighten($topbar-responsive-bg, 60%);
|
||||
border-color: lighten($topbar-responsive-bg, 60%);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 39.9375em) {
|
||||
width: 100%;
|
||||
margin: 0.875rem 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 39.9375em) {
|
||||
padding: 0.75rem;
|
||||
|
||||
.top-bar-title {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
span {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
border: 1px solid $White;
|
||||
border-radius: 5px;
|
||||
padding: 0.25rem 0.45rem;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
|
||||
.menu-icon {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideDown {
|
||||
0% {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0%);
|
||||
}
|
||||
}
|
||||
|
||||
@include breakpoint(small only) {
|
||||
.topbar-responsive-links {
|
||||
// forwards:当动画完成后,保持最后一个属性值(在最后一个关键帧中定义)。
|
||||
// backwards:在 animation-delay 所指定的一段时间内,在动画显示之前,应用开始属性值(在第一个关键帧中定义)。
|
||||
animation-fill-mode: both;
|
||||
animation-duration: 0.5s;
|
||||
width: 100%;
|
||||
// animation: name duration timing-function delay iteration-count direction;
|
||||
// ease 默认。动画以低速开始,然后加快,在结束前变慢。
|
||||
@if $topbar-responsive-animation-type == slide-down {
|
||||
animation: slideDown 1s ease-in;
|
||||
} @else if $topbar-responsive-animation-type == fade-in {
|
||||
animation: fadeIn 1s ease-in;
|
||||
} @else {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<div id="indexCarousel" class="carousel slide" data-ride="carousel">
|
||||
<!-- Indicators -->
|
||||
<ol class="carousel-indicators">
|
||||
<template v-for="(bannerCase, index) in bannerCaseList">
|
||||
<li data-target="#indexCarousel" v-bind:data-slide-to="index" v-bind:class="[index===0?'active':'']"></li>
|
||||
</template>
|
||||
</ol>
|
||||
|
||||
<!-- Wrapper for slides -->
|
||||
<div class="carousel-inner" role="listbox">
|
||||
<template v-for="(bannerCase, index) in bannerCaseList">
|
||||
<div v-bind:class="[index===0?'active':'', 'item']">
|
||||
<img v-bind:src="bannerCase.imageSrc">
|
||||
<div class="carousel-caption">
|
||||
{{bannerCase.title}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- Controls -->
|
||||
<a class="left carousel-control" href="#indexCarousel" role="button" data-slide="prev">
|
||||
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
|
||||
<span class="sr-only">Previous</span>
|
||||
</a>
|
||||
<a class="right carousel-control" href="#indexCarousel" role="button" data-slide="next">
|
||||
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
|
||||
<span class="sr-only">Next</span>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
bannerCaseList: []
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,41 @@
|
||||
<template>
|
||||
<div class="panel-group" id="leftAccordionMenu" role="tablist" aria-multiselectable="true">
|
||||
<div v-for="(parentCategory, index) in categoryList" class="panel panel-default">
|
||||
<div class="panel-heading" role="tab">
|
||||
<h4 class="panel-title">
|
||||
<a role="button" data-toggle="collapse" data-parent="#leftAccordionMenu" v-bind:href="'#collapse'+index" v-bind:class="[index===0?'':'collapsed']" v-bind:aria-expanded="index===0?'true':'false'" v-bind:aria-controls="'collapse'+index">
|
||||
{{parentCategory.name}}
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div v-bind:id="'collapse'+index" v-bind:class="[index===0?'in':'', 'panel-collapse','collapse']" role="tabpanel">
|
||||
<ul v-for="subCategory in parentCategory.sub_cat" class="list-group">
|
||||
<li class="list-group-item">{{subCategory.name}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
categoryList: []
|
||||
};
|
||||
},
|
||||
mounted: function () {
|
||||
this.$nextTick(function () {
|
||||
// 请求案例分类信息
|
||||
this.$http.get('categorys/')
|
||||
.then((res) => {
|
||||
this.categoryList = res.data;
|
||||
}, (err) => {
|
||||
var errorReasonDict = err.body;
|
||||
console.log('---errorReasonDict---');
|
||||
console.log(errorReasonDict);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<form data-toggle="validator" role="form" id="loginForm">
|
||||
<div class="form-group">
|
||||
<i class="fa fa-user-circle fa-lg" aria-hidden="true"></i>
|
||||
<input type="text" class="form-control" name="username" placeholder="请输入用户名" data-pattern-error="用户名长度不足6位" data-required-error="用户名不可以为空" pattern="^.{6,}$" required data-serverValidation>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<i class="fa fa-lock fa-lg" aria-hidden="true"></i>
|
||||
<input type="password" class="form-control" id="password" name="password" placeholder="请输入密码" data-pattern-error="密码长度不足6位" data-required-error="密码不可以为空" pattern="^.{6,}$" required data-serverValidation>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button class="button expanded" v-on:click='postLoginData'>登录</button>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import $ from 'jquery';
|
||||
import Vue from 'vue';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
serverValidationResult: {}
|
||||
};
|
||||
},
|
||||
mounted: function () {
|
||||
this.$nextTick(function () {
|
||||
// 阻止表单的默认提交操作
|
||||
$('#loginForm').submit(function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
$('#loginForm i').css('margin-left', '2%');
|
||||
$('#loginForm input').css('display', 'inline-block').css('width', '70%').css('margin-left', '2%');
|
||||
$('#loginForm').validator({
|
||||
custom: {
|
||||
serverValidation: function ($el) {
|
||||
// 存储服务器验证错误信息的字典为空,则说明所有输入均合法(或者还没提交表单)
|
||||
var inputFieldName = $el.attr('name');
|
||||
if (inputFieldName in this.serverValidationResult) {
|
||||
var result = this.serverValidationResult[inputFieldName];
|
||||
return result;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}.bind(this)
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
postLoginData: function () {
|
||||
var errorNum = $('#loginForm').validator('validate').has('.has-error').length;
|
||||
if (errorNum > 0) {
|
||||
return;
|
||||
}
|
||||
var postData = this.$root.getFormInput('loginForm');
|
||||
this.$http.post('login/', postData)
|
||||
.then((res) => {
|
||||
Vue.http.headers.common['Authorization'] = 'JWT ' + res.data['token'];
|
||||
this.setUserName($('#loginForm input[name="username"]').val());
|
||||
this.$emit('closeLoginModal');
|
||||
}, (err) => {
|
||||
var errorReasonDict = err.body;
|
||||
console.log('---errorReasonDict---');
|
||||
console.log(errorReasonDict);
|
||||
for (var key in errorReasonDict) {
|
||||
this.serverValidationResult[key] = errorReasonDict[key];
|
||||
};
|
||||
$('#loginForm').validator('validate');
|
||||
this.serverValidationResult = {};
|
||||
});
|
||||
},
|
||||
setUserName: function(userName) {
|
||||
this.$store.commit('setUserName', userName);
|
||||
window.sessionStorage.userName = userName;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<form data-toggle="validator" role="form" id="registerForm">
|
||||
<div class="form-group">
|
||||
<i class="fa fa-user-circle fa-lg" aria-hidden="true"></i>
|
||||
<input type="text" class="form-control" name="username" placeholder="请输入用户名" data-pattern-error="用户名长度不足6位" data-required-error="用户名不可以为空" pattern="^.{6,}$" required data-serverValidation>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<i class="fa fa-envelope fa-lg" aria-hidden="true"></i>
|
||||
<input type="email" class="form-control" name="email" placeholder="请输入邮箱地址" data-error="邮箱地址格式非法" required>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<i class="fa fa-envelope fa-lg" aria-hidden="true"></i>
|
||||
<input type="text" class="form-control" name="mobile" placeholder="(非必填)请输入手机号码" data-pattern-error="手机号码格式错误" pattern="^1[34578]\d{9}$">
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<i class="fa fa-lock fa-lg" aria-hidden="true"></i>
|
||||
<input type="password" class="form-control" id="password" name="password" placeholder="请输入密码" data-pattern-error="密码长度不足6位" data-required-error="密码不可以为空" pattern="^.{6,}$" required>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<i class="fa fa-lock fa-lg" aria-hidden="true"></i>
|
||||
<input type="password" class="form-control" name="repeated_password" placeholder="请重复上面所输入的密码" data-match-error="两次输入的密码不一样" data-required-error="必须重复上面的密码" data-match="#password" required>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<img v-bind:src="pictureCodeSrc" style="cursor: pointer" v-on:click='requestForPictureCode'>
|
||||
<input type="text" class="form-control" name="code" placeholder="请输入图片验证码" data-pattern-error="验证码的长度必须为4位" data-required-error="验证码不可以为空" pattern="^.{4,4}$" required data-serverValidation>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<input type="hidden" name="picture_token" v-bind:value="pictureToken"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button class="button expanded" v-on:click='postRegisterData'>注册</button>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import $ from 'jquery';
|
||||
import Vue from 'vue';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pictureCodeSrc: '',
|
||||
pictureToken: '',
|
||||
serverValidationResult: {}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
postRegisterData: function () {
|
||||
var errorNum = $('#registerForm').validator('validate').has('.has-error').length;
|
||||
if (errorNum > 0) {
|
||||
return;
|
||||
}
|
||||
var postData = this.$root.getFormInput('registerForm');
|
||||
this.$http.post('users/', postData)
|
||||
.then((res) => {
|
||||
Vue.http.headers.common['Authorization'] = 'JWT ' + res.data['jwt_token'];
|
||||
this.setUserName($('#registerForm input[name="username"]').val());
|
||||
this.$emit('closeRegisterModal');
|
||||
}, (err) => {
|
||||
var errorReasonDict = err.body;
|
||||
console.log('---errorReasonDict---');
|
||||
console.log(errorReasonDict);
|
||||
for (var key in errorReasonDict) {
|
||||
if (key === 'non_field_errors') {
|
||||
var reason = errorReasonDict[key][0];
|
||||
if (reason.indexOf('令牌') === -1) {
|
||||
this.serverValidationResult['code'] = errorReasonDict[key];
|
||||
}
|
||||
this.requestForPictureCode();
|
||||
} else if (key === 'picture_token') {
|
||||
this.requestForPictureCode();
|
||||
} else {
|
||||
this.serverValidationResult[key] = errorReasonDict[key];
|
||||
}
|
||||
};
|
||||
$('#registerForm').validator('validate');
|
||||
this.serverValidationResult = {};
|
||||
});
|
||||
},
|
||||
// 请求图片验证码
|
||||
requestForPictureCode: function () {
|
||||
this.$http.get('picturecodes/')
|
||||
.then((res) => {
|
||||
this.pictureCodeSrc = this.$root.$data.requestHost + res.data['cptch_image'];
|
||||
this.pictureToken = res.data['cptch_key'];
|
||||
$('#registerForm input[name="code"]').val('');
|
||||
}, (err) => {
|
||||
console.log('图片验证码请求错误');
|
||||
console.log(err);
|
||||
});
|
||||
},
|
||||
setUserName: function(userName) {
|
||||
this.$store.commit('setUserName', userName);
|
||||
window.sessionStorage.userName = userName;
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this.$nextTick(function () {
|
||||
// 阻止表单的默认提交操作
|
||||
$('#registerForm').submit(function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
$('#registerForm i').css('margin-left', '2%');
|
||||
$('#registerForm input[name]').css('display', 'inline-block').css('width', '70%').css('margin-left', '2%');
|
||||
$('#registerForm').validator({
|
||||
custom: {
|
||||
serverValidation: function ($el) {
|
||||
// 存储服务器验证错误信息的字典为空,则说明所有输入均合法(或者还没提交表单)
|
||||
var inputFieldName = $el.attr('name');
|
||||
if (inputFieldName in this.serverValidationResult) {
|
||||
var result = this.serverValidationResult[inputFieldName];
|
||||
return result;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}.bind(this)
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,199 @@
|
||||
<template>
|
||||
<form id="richTextEditorForm">
|
||||
|
||||
<div class="form-group">
|
||||
<label>案例名称:</label>
|
||||
<input type="text" class="form-control" name="name" placeholder="请输入案例名称" data-required-error="案例名称不可以为空" required>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>案例简短描述:</label>
|
||||
<input type="text" class="form-control" name="cases_brief" placeholder="请输入案例简短描述" data-required-error="案例简短描述不可以为空" required>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>案例类别:</label>
|
||||
<select name="category_name">
|
||||
<optgroup v-for="parentCategory in categoryList" v-bind:label="parentCategory.name">
|
||||
<option v-for="subCategory in parentCategory.sub_cat">{{subCategory.name}}</option>
|
||||
</optgroup>
|
||||
</select>
|
||||
<div class="help-block with-errors"></div>
|
||||
</div>
|
||||
|
||||
<textarea name="cases_desc">
|
||||
<p style="text-align: center;">
|
||||
<img title="TinyMCE Logo" src="//www.tinymce.com/images/glyph-tinymce@2x.png" alt="TinyMCE Logo" width="110"
|
||||
height="97"/></p>
|
||||
<h1 style="text-align: center;">Welcome to the TinyMCE editor demo!</h1>
|
||||
<p>Please try out the features provided in this basic example.
|
||||
<br>Note that any
|
||||
<strong>MoxieManager</strong>file and image management functionality in this example is part of our commercial offering – the demo is to show the integration.
|
||||
</p>
|
||||
<h2>Got questions or need help?</h2>
|
||||
<ul>
|
||||
<li>Our<a href="https://www.tinymce.com/docs/">documentation</a>is a great resource for learning how to configure TinyMCE.</li>
|
||||
<li>Have a specific question? Visit the<a href="https://community.tinymce.com/forum/" target="_blank">Community Forum</a>.</li>
|
||||
<li>We also offer enterprise grade support as part of<a
|
||||
href="www.tinymce.com/pricing">TinyMCE Enterprise</a>.</li></ul>
|
||||
<h2>A simple table to play with</h2>
|
||||
<table style="text-align: center;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Product</th>
|
||||
<th>Cost</th>
|
||||
<th>Really?</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>TinyMCE</td>
|
||||
<td>Free</td>
|
||||
<td>YES!</td></tr>
|
||||
<tr>
|
||||
<td>Plupload</td>
|
||||
<td>Free</td>
|
||||
<td>YES!</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2>Found a bug?</h2>
|
||||
<p>If you think you have found a bug please create an issue on the
|
||||
<a href="https://github.com/tinymce/tinymce/issues">GitHub repo</a>to report it to the developers.
|
||||
</p>
|
||||
<h2>Finally ...</h2>
|
||||
<p>Don't forget to check out our other product
|
||||
<a href="http://www.plupload.com" target="_blank">Plupload</a>, your ultimate upload solution featuring HTML5 upload support.</p>
|
||||
<p>Thanks for supporting TinyMCE! We hope it helps you and your users create great content.
|
||||
<br>All the best from the TinyMCE team.</p>
|
||||
</textarea>
|
||||
|
||||
<div class="form-group">
|
||||
<label>案例封面图片:</label>
|
||||
<input type="file" v-on:change="uploadCoverPicture" id="coverPictureSelector">
|
||||
<label>上传进度:{{uploadProgress}}%</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<input type="hidden" name="cases_front_image" v-bind:value="coverPictureURL"/>
|
||||
</div>
|
||||
|
||||
<button class="button expanded" v-on:click='postRichTextEditorData'>提交</button>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import $ from 'jquery';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
categoryList: [],
|
||||
coverPictureURL: '',
|
||||
uploadProgress: 0.0
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
postRichTextEditorData: function () {
|
||||
window.tinymce.activeEditor.uploadImages(function(success) {
|
||||
var postData = this.$root.getFormInput('richTextEditorForm');
|
||||
this.$http.post('cases/', postData).then(function(res) {
|
||||
console.log('---表单提交成功---');
|
||||
}, (err) => {
|
||||
console.log('---err.body---');
|
||||
console.log(err.body);
|
||||
});
|
||||
}.bind(this));
|
||||
},
|
||||
uploadCoverPicture (event) {
|
||||
this.uploadProgress = 0.0;
|
||||
this.coverPictureURL = '';
|
||||
let file = event.target.files[0];
|
||||
if (file) {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
this.$http.post('uploadfile/case_cover_picture/', formData, {
|
||||
progress: function(event) {
|
||||
this.uploadProgress = parseFloat(event.loaded / event.total * 100);
|
||||
}.bind(this)
|
||||
}).then((res) => {
|
||||
this.coverPictureURL = res.data['location'];
|
||||
console.log('---this.coverPictureURL---');
|
||||
console.log(this.coverPictureURL);
|
||||
}, (err) => {
|
||||
this.uploadProgress = 0.0;
|
||||
var errorReasonDict = err.body;
|
||||
console.log('---errorReasonDict---');
|
||||
console.log(errorReasonDict);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this.$nextTick(function () {
|
||||
// 阻止表单的默认提交操作
|
||||
$('#richTextEditorForm').submit(function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
// 请求案例分类信息
|
||||
this.$http.get('categorys/')
|
||||
.then((res) => {
|
||||
this.categoryList = res.data;
|
||||
}, (err) => {
|
||||
var errorReasonDict = err.body;
|
||||
console.log('---errorReasonDict---');
|
||||
console.log(errorReasonDict);
|
||||
});
|
||||
// 如果还没加载强大的富文本编辑器TinyMCE,则进行动态请求并加载
|
||||
if (!window.tinymce) {
|
||||
$.getScript('https://cloud.tinymce.com/stable/tinymce.min.js?apiKey=w1jnifw6jyuhsi04yjizbcmplt1s0w5zks3u7xeaitd7samr')
|
||||
.done(function() {
|
||||
// 要等到下一次DOM更新完成(即window.tinymce已经生成)后才进行tinymce的初始化
|
||||
this.$nextTick(function () {
|
||||
// 初始化富文本编辑器TinyMCE
|
||||
window.tinymce.init({
|
||||
selector: 'textarea',
|
||||
branding: false,
|
||||
language_url: this.$root.$data.requestHost + '/static/zh_CN.js', // site absolute URL
|
||||
height: 500,
|
||||
menubar: false,
|
||||
plugins: [
|
||||
'advlist autolink lists link image charmap print preview anchor textcolor colorpicker',
|
||||
'searchreplace visualblocks code fullscreen',
|
||||
'insertdatetime media table contextmenu paste code help'
|
||||
],
|
||||
toolbar: 'insert | undo redo | formatselect image | bold italic strikethrough forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | removeformat | help',
|
||||
// 配置了该选项后,才能进行上传文件
|
||||
images_upload_url: this.$root.$data.requestHost + '/uploadfile/rich_text_picture/',
|
||||
images_upload_handler: function (blobInfo, success, failure) {
|
||||
var formData = new FormData();
|
||||
formData.append('file', blobInfo.blob(), blobInfo.filename());
|
||||
this.$http.post('uploadfile/rich_text_picture/', formData).then((res) => {
|
||||
success(res.data['location']);
|
||||
}, (err) => {
|
||||
var errorReasonDict = err.body;
|
||||
console.log('---errorReasonDict---');
|
||||
console.log(errorReasonDict);
|
||||
failure(errorReasonDict['detail']);
|
||||
});
|
||||
}.bind(this),
|
||||
content_css: [
|
||||
'//fonts.googleapis.com/css?family=Lato:300,300i,400,400i',
|
||||
'//www.tinymce.com/css/codepen.min.css']
|
||||
});
|
||||
});
|
||||
}.bind(this))
|
||||
.fail(function() {
|
||||
console.log('TinyMCE加载失败。。。');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
padding: 5px
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav class="navbar navbar-default">
|
||||
<!-- 占满整行 -->
|
||||
<div class="container-fluid">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">APP Inventor案例库</a>
|
||||
</div>
|
||||
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav" id="navUl">
|
||||
<li><a href="/index">首页<span class="sr-only">(current)</span></a></li>
|
||||
<li><a href="#">案例</a></li>
|
||||
<li><a href="/editCase">发表</a></li>
|
||||
<li><a href="#">问答</a></li>
|
||||
</ul>
|
||||
<form class="navbar-form navbar-left">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="请输入搜索关键字">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-default">搜索</button>
|
||||
</form>
|
||||
<template v-if="userName.length > 0">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><button type="button" class="btn btn-default navbar-btn" v-on:click='logout'>注销</button></li>
|
||||
</ul>
|
||||
</template>
|
||||
<template v-else>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><button type="button" class="btn btn-default navbar-btn" v-on:click="openLoginModal">登录</button></li>
|
||||
<li><p class="navbar-text">Or</p></li>
|
||||
<li><button type="button" class="btn btn-default navbar-btn" v-on:click="openRegisterModal">注册</button></li>
|
||||
</ul>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="modal fade" id="loginModal" tabindex="-1" role="dialog" aria-labelledby="loginModal">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title text-center">登录</h4>
|
||||
</div>
|
||||
<login-modal ref="loginModal" v-on:closeLoginModal="closeLoginModal"></login-modal>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="registerModal" tabindex="-1" role="dialog" aria-labelledby="registerModal">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title text-center">注册</h4>
|
||||
</div>
|
||||
<register-modal ref="registerModal" v-on:closeRegisterModal="closeRegisterModal"></register-modal>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import $ from 'jquery';
|
||||
import Vue from 'vue';
|
||||
import loginModal from './loginModal.vue';
|
||||
import registerModal from './registerModal.vue';
|
||||
export default {
|
||||
// 模板<template>默认替换挂载元素,如果 replace 选项为 false,模板将插入挂载元素内
|
||||
replace: true,
|
||||
props: {
|
||||
activeIndex: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
loginModal,
|
||||
registerModal
|
||||
},
|
||||
computed: {
|
||||
userName () {
|
||||
return this.$store.state.userName;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
closeLoginModal: function () {
|
||||
$('#loginModal').modal('hide');
|
||||
},
|
||||
closeRegisterModal: function () {
|
||||
$('#registerModal').modal('hide');
|
||||
},
|
||||
openLoginModal: function () {
|
||||
// backdrop 为 static 时,点击模态对话框的外部区域不会将其关闭
|
||||
// keyboard 为 false 时,按下 Esc 键不会关闭 Modal
|
||||
$('#loginModal').modal({backdrop: 'static', keyboard: false});
|
||||
},
|
||||
openRegisterModal: function () {
|
||||
// backdrop 为 static 时,点击模态对话框的外部区域不会将其关闭
|
||||
// keyboard 为 false 时,按下 Esc 键不会关闭 Modal
|
||||
$('#registerModal').modal({backdrop: 'static', keyboard: false});
|
||||
},
|
||||
logout: function () {
|
||||
this.$store.commit('setUserName', '');
|
||||
window.sessionStorage.userName = '';
|
||||
delete Vue.http.headers.common['Authorization'];
|
||||
this.$router.go(0);
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this.$nextTick(function () {
|
||||
var $selector = $('#navUl li');
|
||||
$($selector[parseInt(this.activeIndex)]).addClass('active');
|
||||
$('#registerModal').on('show.bs.modal', function () {
|
||||
// 请求图片验证码
|
||||
this.$refs.registerModal.requestForPictureCode();
|
||||
}.bind(this));
|
||||
if (this.$route.query.hasOwnProperty('needToLogin')) {
|
||||
this.openLoginModal();
|
||||
}
|
||||
console.log('---this.$store.state---');
|
||||
console.log(this.$store.state);
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -6,14 +6,11 @@ import routes from './routers';
|
||||
import Alert from './libs/alert';
|
||||
import store from './vuex/user';
|
||||
import FastClick from 'fastclick';
|
||||
import $ from 'jquery';
|
||||
import Utils from './utils';
|
||||
Vue.use(VueRouter);
|
||||
Vue.use(Alert);
|
||||
Vue.use(VueResource);
|
||||
|
||||
$.ajaxSettings.crossDomain = true;
|
||||
|
||||
/*
|
||||
Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组
|
||||
Vue.filter('my-filter', function (value前) { return value后 })用来给Vue注册自定义过滤器
|
||||
@@ -38,8 +35,8 @@ const router = new VueRouter({
|
||||
FastClick.attach(document.body);
|
||||
|
||||
// 处理刷新的时候vuex被清空但是用户已经登录的情况
|
||||
if (window.sessionStorage.user) {
|
||||
store.dispatch('setUserInfo', JSON.parse(window.sessionStorage.user));
|
||||
if (window.sessionStorage.userName) {
|
||||
store.commit('setUserName', window.sessionStorage.userName);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -55,13 +52,15 @@ if (window.sessionStorage.user) {
|
||||
next()进行管道中的下一个钩子;next(false)返回到from参数对应的URL;next(其他URL)表示重定向
|
||||
*/
|
||||
router.beforeEach((to, from, next) => {
|
||||
console.log('---store.state---');
|
||||
console.log(store.state);
|
||||
if (to.matched.some(record => record.meta.requiresAuth)) {
|
||||
if (store.state.userInfo.userId) {
|
||||
if (store.state.userName.length > 0) {
|
||||
next();
|
||||
} else {
|
||||
next({
|
||||
path: '/login',
|
||||
query: { redirect: to.fullPath }
|
||||
path: '/index',
|
||||
query: { redirect: to.fullPath, needToLogin: 'true' }
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@@ -85,11 +84,5 @@ new Vue({
|
||||
return {
|
||||
requestHost: requestHost
|
||||
};
|
||||
},
|
||||
mounted: function () {
|
||||
this.$nextTick(function () {
|
||||
// 使得Foundation框架生效所必须的操作
|
||||
$(document).foundation();
|
||||
});
|
||||
}
|
||||
}).$mount('#app');
|
||||
|
||||
@@ -18,21 +18,22 @@ const routers = [{
|
||||
});
|
||||
}
|
||||
}, {
|
||||
path: '/register',
|
||||
name: 'register',
|
||||
path: '/index',
|
||||
name: 'index',
|
||||
component(resolve) {
|
||||
require.ensure(['./views/register.vue'], () => {
|
||||
resolve(require('./views/register.vue'));
|
||||
require.ensure(['./views/index.vue'], () => {
|
||||
resolve(require('./views/index.vue'));
|
||||
});
|
||||
}
|
||||
}, {
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
path: '/editCase',
|
||||
name: 'editCase',
|
||||
component(resolve) {
|
||||
require.ensure(['./views/login.vue'], () => {
|
||||
resolve(require('./views/login.vue'));
|
||||
require.ensure(['./views/editCase.vue'], () => {
|
||||
resolve(require('./views/editCase.vue'));
|
||||
});
|
||||
}
|
||||
},
|
||||
meta: { requiresAuth: true }
|
||||
}, {
|
||||
path: '*',
|
||||
component(resolve) {
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
import $ from 'jquery';
|
||||
|
||||
const jumpToThisPage = function (name, params) {
|
||||
this.$router.push({name: name, params: params});
|
||||
};
|
||||
|
||||
export default {jumpToThisPage};
|
||||
const getFormInput = function (formId) {
|
||||
var postData = {};
|
||||
var fieldArray = $('#' + formId).serializeArray();
|
||||
$.each(fieldArray, function (i, field) {
|
||||
postData[field.name] = field.value;
|
||||
});
|
||||
console.log('---请求来自' + formId + '---');
|
||||
console.log('---数据序列化为---');
|
||||
console.log(postData);
|
||||
return postData;
|
||||
};
|
||||
|
||||
export default {jumpToThisPage, getFormInput};
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<top-bar activeIndex='2'>
|
||||
</top-bar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<rich-text-editor>
|
||||
</rich-text-editor>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import topBar from '../components/topBar.vue';
|
||||
import richTextEditor from '../components/richTextEditor.vue';
|
||||
export default {
|
||||
components: {
|
||||
topBar,
|
||||
richTextEditor
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
caseList: []
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -1,19 +1,49 @@
|
||||
<template>
|
||||
<ai-head page-type="登录">
|
||||
</ai-head>
|
||||
<div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<top-bar activeIndex='0'>
|
||||
</top-bar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<index-carousel>
|
||||
</index-carousel>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<left-accordion-menu>
|
||||
</left-accordion-menu>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<div class="row">
|
||||
<div v-for="caseObj in caseList" class="col-sm-4">
|
||||
<case-media-object thumbnailSrc=caseObj.thumbnailSrc title=caseObj.tile content=caseObj.content>
|
||||
</case-media-object>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import aiHead from '../components/header.vue';
|
||||
import $ from 'jquery';
|
||||
import topBar from '../components/topBar.vue';
|
||||
import leftAccordionMenu from '../components/leftAccordionMenu.vue';
|
||||
import caseMediaObject from '../components/caseMediaObject.vue';
|
||||
import indexCarousel from '../components/indexCarousel.vue';
|
||||
export default {
|
||||
components: {
|
||||
aiHead
|
||||
topBar,
|
||||
leftAccordionMenu,
|
||||
caseMediaObject,
|
||||
indexCarousel
|
||||
},
|
||||
mounted: function () {
|
||||
this.$nextTick(function () {
|
||||
// 使得Foundation框架生效所必须的操作
|
||||
$(document).foundation();
|
||||
});
|
||||
data() {
|
||||
return {
|
||||
caseList: []
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
<template>
|
||||
<!-- 取消H5的默认表单验证功能,以免与Foundation的Abide发生冲突 -->
|
||||
<form data-abide novalidate>
|
||||
<div class="row form-icons">
|
||||
<h4>登录</h4>
|
||||
<!-- 总的错误消息提示框,alert标识的是颜色 -->
|
||||
<div data-abide-error class="column small-12 alert callout" style="display: none">
|
||||
<p><i class="fi-alert"></i> 表单输入有错误</p>
|
||||
</div>
|
||||
<div class="column small-12 input-group">
|
||||
<span class="input-group-label">
|
||||
<i class="fi fi-torso"></i>
|
||||
</span>
|
||||
<!-- required表示为必填项 -->
|
||||
<input class="input-group-field" type="text" name="username" placeholder="请输入用户名" required
|
||||
pattern="not-shorter-than-six">
|
||||
<br/>
|
||||
<!-- 对应的错误提示信息 -->
|
||||
<span class="form-error">用户名长度不足6位</span>
|
||||
</div>
|
||||
|
||||
<div class="column small-12 input-group">
|
||||
<span class="input-group-label">
|
||||
<i class="fi fi-key"></i>
|
||||
</span>
|
||||
<input class="input-group-field" type="password" name="password" id="Password" placeholder="请输入密码"
|
||||
required pattern="not-shorter-than-six">
|
||||
<label>
|
||||
<span class="form-error">密码长度不足6位</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<button class="button expanded">登录</button>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import $ from 'jquery';
|
||||
|
||||
export default {
|
||||
mounted: function () {
|
||||
this.$nextTick(function () {
|
||||
// 添加自定义Pattern
|
||||
window.Foundation.Abide.defaults.patterns['not-shorter-than-six'] = /^.{6,}$/;
|
||||
// 使得Foundation框架生效所必须的操作
|
||||
$(document).foundation();
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "../assets/scss/constant";
|
||||
|
||||
form {
|
||||
.form-icons {
|
||||
text-align: center;
|
||||
|
||||
h4 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.form-error {
|
||||
font-size: 1rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.input-group-label {
|
||||
background-color: $primary-color;
|
||||
border-color: $primary-color;
|
||||
}
|
||||
|
||||
.input-group-field {
|
||||
border-color: $primary-color;
|
||||
}
|
||||
|
||||
.fi {
|
||||
color: white;
|
||||
width: 1rem; // makes the width of icon labels equal
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,166 +0,0 @@
|
||||
<template>
|
||||
<!-- 取消H5的默认表单验证功能,以免与Foundation的Abide发生冲突 -->
|
||||
<form data-abide novalidate id="RegisterForm">
|
||||
<div class="row form-icons">
|
||||
<h4>注册</h4>
|
||||
<!-- 总的错误消息提示框,alert标识的是颜色 -->
|
||||
<div data-abide-error class="column small-12 alert callout" style="display: none">
|
||||
<p><i class="fi-alert"></i> 表单输入有错误</p>
|
||||
</div>
|
||||
<div class="column small-12 input-group">
|
||||
<span class="input-group-label">
|
||||
<i class="fi fi-torso"></i>
|
||||
</span>
|
||||
<!-- required表示为必填项 -->
|
||||
<input class="input-group-field" type="text" name="username" placeholder="请输入用户名" required
|
||||
pattern="not-shorter-than-six">
|
||||
<br/>
|
||||
<!-- 对应的错误提示信息 -->
|
||||
<span class="form-error">用户名长度不足6位</span>
|
||||
</div>
|
||||
|
||||
<div class="column small-12 input-group">
|
||||
<span class="input-group-label">
|
||||
<i class="fi fi-mail"></i>
|
||||
</span>
|
||||
<input class="input-group-field" type="text" name="email" placeholder="请输入邮箱地址" required
|
||||
pattern="email">
|
||||
<label>
|
||||
<span class="form-error">邮箱地址格式非法</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="column small-12 input-group">
|
||||
<span class="input-group-label">
|
||||
<i class="fi fi-telephone"></i>
|
||||
</span>
|
||||
<input class="input-group-field" type="text" name="mobile" placeholder="(非必填)请输入手机号码"
|
||||
pattern="telephone">
|
||||
<label>
|
||||
<span class="form-error">手机号码格式非法</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="column small-12 input-group">
|
||||
<span class="input-group-label">
|
||||
<i class="fi fi-key"></i>
|
||||
</span>
|
||||
<input class="input-group-field" type="password" name="password" id="Password" placeholder="请输入密码"
|
||||
required pattern="not-shorter-than-six">
|
||||
<label>
|
||||
<span class="form-error">密码长度不足6位</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="column small-12 input-group">
|
||||
<span class="input-group-label">
|
||||
<i class="fi fi-key"></i>
|
||||
</span>
|
||||
<input class="input-group-field" type="password" name="repeated_password" placeholder="请重复上面所输入的密码"
|
||||
required data-equalto="Password">
|
||||
<div class="form-error">两次输入的密码不一样</div>
|
||||
</div>
|
||||
|
||||
<div class="column small-12 input-group">
|
||||
<img v-bind:src="pictureCodeSrc">
|
||||
<input class="input-group-field" type="text" name="code" placeholder="请输入图片验证码"
|
||||
required pattern="length-equalto-four">
|
||||
<div class="form-error">图片验证码长度为4</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="picture_token" v-bind:value="pictureToken"/>
|
||||
</div>
|
||||
<button class="button expanded" v-on:click='postRegisterData'>注册</button>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import $ from 'jquery';
|
||||
import Vue from 'vue';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pictureCodeSrc: '',
|
||||
pictureToken: ''
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
postRegisterData: function () {
|
||||
var postData = {};
|
||||
var fieldArray = $('#RegisterForm').serializeArray();
|
||||
$.each(fieldArray, function (i, field) {
|
||||
postData[field.name] = field.value;
|
||||
});
|
||||
this.$http.post(this.$root.$data.requestHost + '/users/', postData)
|
||||
.then((res) => {
|
||||
Vue.http.headers.common['Authorization'] = 'JWT ' + res.data['jwt_token'];
|
||||
console.log('JWT ' + res.data['jwt_token']);
|
||||
this.$root.jumpToThisPage('/');
|
||||
}, (err) => {
|
||||
console.log('网络请求错误');
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
this.$nextTick(function () {
|
||||
// 添加自定义Pattern
|
||||
window.Foundation.Abide.defaults.patterns['not-shorter-than-six'] = /^.{6,}$/;
|
||||
window.Foundation.Abide.defaults.patterns['length-equalto-four'] = /^.{4,4}$/;
|
||||
window.Foundation.Abide.defaults.patterns['telephone'] = /^1[34578]\d{9}$/;
|
||||
// 使得Foundation框架生效所必须的操作
|
||||
$(document).foundation();
|
||||
// 请求图片验证码
|
||||
this.$http.get('picturecodes/')
|
||||
.then((res) => {
|
||||
this.pictureCodeSrc = this.$root.$data.requestHost + res.data['cptch_image'];
|
||||
this.pictureToken = res.data['cptch_key'];
|
||||
}, (err) => {
|
||||
console.log('图片验证码请求错误');
|
||||
console.log(err);
|
||||
});
|
||||
// 阻止表单的默认提交操作
|
||||
$('#RegisterForm').submit(function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "../assets/scss/constant";
|
||||
|
||||
form {
|
||||
.form-icons {
|
||||
text-align: center;
|
||||
|
||||
h4 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.form-error {
|
||||
font-size: 1rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.input-group-label {
|
||||
background-color: $primary-color;
|
||||
border-color: $primary-color;
|
||||
}
|
||||
|
||||
.input-group-field {
|
||||
border-color: $primary-color;
|
||||
}
|
||||
|
||||
.fi {
|
||||
color: white;
|
||||
width: 1rem; // makes the width of icon labels equal
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -4,29 +4,12 @@ Vue.use(Vuex);
|
||||
|
||||
const userStore = new Vuex.Store({
|
||||
state: {
|
||||
userInfo: {}
|
||||
},
|
||||
getters: {
|
||||
getUserInfo(state) {
|
||||
return state.userInfo;
|
||||
}
|
||||
userName: ''
|
||||
},
|
||||
// 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation
|
||||
mutations: {
|
||||
setUserInfo(state, userInfo) {
|
||||
state.userInfo = userInfo;
|
||||
}
|
||||
},
|
||||
/*
|
||||
Action 类似于 mutation,不同在于:①Action提交的是mutation,而不是直接变更状态;②Action可以包含任意异步操作
|
||||
Action 函数接受一个与store 实例具有相同方法和属性的context对象,因此你可以调用context.commit提交一个mutation
|
||||
或者通过context.state和context.getters来获取state和getters。但是context 对象并不是store实例本身
|
||||
*/
|
||||
actions: {
|
||||
// {commit}这种写法属于ES6新特性,属于对象的解构赋值,得到的commit相当于context.commit
|
||||
setUserInfo({ commit }, user) {
|
||||
// user为mutation的载荷(payload),这里会引发setUserInfo(state, user)这个mutation
|
||||
commit('setUserInfo', user);
|
||||
setUserName(state, userName) {
|
||||
state.userName = userName;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# HTML笔记
|
||||
|
||||
## 1.display属性
|
||||
|
||||
①block:块级元素,前后会带有换行符
|
||||
(代表元素有:DIV, FORM, TABLE, P, PRE, H1~H6, DL, OL, UL)
|
||||
②inline:内联元素,不自动进行换行符
|
||||
(代表元素有:SPAN, A, STRONG, EM, LABEL, INPUT, SELECT, TEXTAREA, IMG, BR)
|
||||
③inline-block:将对象呈现为inline对象,但是对象的内容作为block对象呈现。使其既具有block的宽度高度特性又具有inline的同行特性
|
||||
@@ -1,6 +1,6 @@
|
||||
# 里程碑
|
||||
|
||||
1. 完成后端Django REST framework项目框架(附注释)
|
||||
2. 完成前端webpack+Vue全家桶的前端项目框架(附注释)
|
||||
3. 利用Foundation完成了顶部导航栏、注册、登录的页面设计
|
||||
4. 完成注册页面和逻辑功能
|
||||
1. 完成后端Xadmin+Django全家桶(①django;②django-REST-framework;③django-filter;④django-simple-captcha;⑤django-REST-framework-jwt )项目框架(附注释)
|
||||
2. 完成前端webpack+Vue全家桶(①Vue2;②Vue-router;③Vue-resource;④Vuex)的前端项目框架(附注释)
|
||||
3. 利用BootStrap3完成了顶部导航栏、注册、登录、案例发布的页面设计
|
||||
4. 利用Django REST framework完成了注册、登录、案例发布的后台业务逻辑代码的编写
|
||||
@@ -0,0 +1,16 @@
|
||||
# Vue笔记
|
||||
|
||||
1. v-model是v-bind和v-on的语法糖。差不多就相当于下面代码:
|
||||
|
||||
```
|
||||
<input id="a" class="check" name="style" type="checkbox" v-bind:checked="need" v-on:change="change">
|
||||
|
||||
data:{
|
||||
need:true
|
||||
},
|
||||
methods:{
|
||||
change:function(e){
|
||||
this.need = e.target.value;
|
||||
}
|
||||
}
|
||||
```
|
||||
+5
-14
@@ -3,15 +3,13 @@ __author__ = 'HymanLu'
|
||||
|
||||
import xadmin
|
||||
from .models import Cases, CasesCategory, CasesImage, Banner, HotSearchWords
|
||||
from .models import IndexAd
|
||||
|
||||
class CasesAdmin(object):
|
||||
list_display = ["name", "click_num", "sold_num", "fav_num", "cases_num", "market_price",
|
||||
"shop_price", "cases_brief", "cases_desc", "is_new", "is_hot", "add_time"]
|
||||
list_display = ["name", "click_num", "fav_num",
|
||||
"cases_brief", "cases_desc", "add_time"]
|
||||
search_fields = ['name', ]
|
||||
list_editable = ["is_hot", ]
|
||||
list_filter = ["name", "click_num", "sold_num", "fav_num", "cases_num", "market_price",
|
||||
"shop_price", "is_new", "is_hot", "add_time", "category__name"]
|
||||
list_filter = ["name", "click_num", "fav_num",
|
||||
"add_time", "category__name"]
|
||||
style_fields = {"cases_desc": "ueditor"}
|
||||
|
||||
class CasesImagesInline(object):
|
||||
@@ -47,14 +45,7 @@ class HotSearchAdmin(object):
|
||||
list_display = ["keywords", "index", "add_time"]
|
||||
|
||||
|
||||
class IndexAdAdmin(object):
|
||||
list_display = ["category", "cases"]
|
||||
|
||||
|
||||
xadmin.site.register(Cases, CasesAdmin)
|
||||
xadmin.site.register(CasesCategory, CasesCategoryAdmin)
|
||||
xadmin.site.register(Banner, BannerCasesAdmin)
|
||||
|
||||
xadmin.site.register(HotSearchWords, HotSearchAdmin)
|
||||
xadmin.site.register(IndexAd, IndexAdAdmin)
|
||||
|
||||
xadmin.site.register(HotSearchWords, HotSearchAdmin)
|
||||
@@ -11,8 +11,6 @@ class CasesFilter(django_filters.rest_framework.FilterSet):
|
||||
"""
|
||||
案例的过滤类
|
||||
"""
|
||||
pricemin = django_filters.NumberFilter(name='shop_price', help_text="最低价格",lookup_expr='gte')
|
||||
pricemax = django_filters.NumberFilter(name='shop_price', lookup_expr='lte')
|
||||
top_category = django_filters.NumberFilter(method='top_category_filter')
|
||||
|
||||
|
||||
@@ -22,4 +20,4 @@ class CasesFilter(django_filters.rest_framework.FilterSet):
|
||||
|
||||
class Meta:
|
||||
model = Cases
|
||||
fields = ['pricemin', 'pricemax', 'is_hot', 'is_new']
|
||||
fields = []
|
||||
@@ -0,0 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.7 on 2017-11-14 17:39
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('cases', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='indexad',
|
||||
name='cases',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='indexad',
|
||||
name='category',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='cases',
|
||||
name='cases_num',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='cases',
|
||||
name='cases_sn',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='cases',
|
||||
name='is_hot',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='cases',
|
||||
name='is_new',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='cases',
|
||||
name='market_price',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='cases',
|
||||
name='ship_free',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='cases',
|
||||
name='shop_price',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='cases',
|
||||
name='sold_num',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='IndexAd',
|
||||
),
|
||||
]
|
||||
+4
-24
@@ -34,21 +34,14 @@ class Cases(models.Model):
|
||||
案例
|
||||
"""
|
||||
category = models.ForeignKey(CasesCategory, verbose_name="案例类目")
|
||||
cases_sn = models.CharField(max_length=50, default="", verbose_name="案例唯一货号")
|
||||
name = models.CharField(max_length=100, verbose_name="案例名")
|
||||
click_num = models.IntegerField(default=0, verbose_name="点击数")
|
||||
sold_num = models.IntegerField(default=0, verbose_name="案例销售量")
|
||||
fav_num = models.IntegerField(default=0, verbose_name="收藏数")
|
||||
cases_num = models.IntegerField(default=0, verbose_name="库存数")
|
||||
market_price = models.FloatField(default=0, verbose_name="市场价格")
|
||||
shop_price = models.FloatField(default=0, verbose_name="本店价格")
|
||||
cases_brief = models.TextField(max_length=500, verbose_name="案例简短描述")
|
||||
cases_desc = UEditorField(verbose_name=u"内容", imagePath="cases/images/", width=1000, height=300,
|
||||
filePath="cases/files/", default='')
|
||||
ship_free = models.BooleanField(default=True, verbose_name="是否承担运费")
|
||||
cases_front_image = models.ImageField(upload_to="cases/images/", null=True, blank=True, verbose_name="封面图")
|
||||
is_new = models.BooleanField(default=False, verbose_name="是否新品")
|
||||
is_hot = models.BooleanField(default=False, verbose_name="是否热销")
|
||||
#cases_desc = UEditorField(verbose_name=u"内容", imagePath="cases/images/", width=1000, height=300, filePath="cases/files/", default='')
|
||||
cases_desc = models.TextField(max_length=10000, verbose_name="案例正文内容")
|
||||
#cases_front_image = models.ImageField(upload_to="cases/images/", null=True, blank=True, verbose_name="封面图")
|
||||
cases_front_image = models.CharField(max_length=200, verbose_name="封面图URL", blank=True)
|
||||
add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")
|
||||
|
||||
class Meta:
|
||||
@@ -58,19 +51,6 @@ class Cases(models.Model):
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class IndexAd(models.Model):
|
||||
category = models.ForeignKey(CasesCategory, related_name='category',verbose_name="案例类目")
|
||||
cases =models.ForeignKey(Cases, related_name='cases')
|
||||
|
||||
class Meta:
|
||||
verbose_name = '首页案例类别广告'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return self.cases.name
|
||||
|
||||
|
||||
class CasesImage(models.Model):
|
||||
"""
|
||||
案例轮播图
|
||||
|
||||
+18
-32
@@ -3,9 +3,7 @@ __author__ = 'HymanLu'
|
||||
|
||||
from rest_framework import serializers
|
||||
from django.db.models import Q
|
||||
|
||||
from cases.models import Cases, CasesCategory, HotSearchWords, CasesImage, Banner
|
||||
from cases.models import IndexAd
|
||||
|
||||
|
||||
class CategorySerializer2(serializers.ModelSerializer):
|
||||
@@ -26,13 +24,26 @@ class CasesImageSerializer(serializers.ModelSerializer):
|
||||
model = CasesImage
|
||||
fields = ("image", )
|
||||
|
||||
|
||||
class CasesSerializer(serializers.ModelSerializer):
|
||||
category = CategorySerializer()
|
||||
images = CasesImageSerializer(many=True)
|
||||
#category = CategorySerializer()
|
||||
#images = CasesImageSerializer(many=True)
|
||||
category_name = serializers.CharField(required=True, write_only=True, label="案例类别名称",
|
||||
error_messages={
|
||||
"required": "请输入案例类别名称",
|
||||
"blank": "请输入案例类别名称"
|
||||
})
|
||||
def validate(self, attrs):
|
||||
category_name = attrs["category_name"]
|
||||
category = CasesCategory.objects.get(Q(name=category_name))
|
||||
if not category:
|
||||
raise serializers.ValidationError("该案例类别不存在")
|
||||
attrs["category"] = category
|
||||
del attrs["category_name"]
|
||||
return attrs
|
||||
class Meta:
|
||||
model = Cases
|
||||
fields = "__all__"
|
||||
#fields = "__all__"
|
||||
fields = ("category_name", "name", "cases_brief", "cases_desc", "cases_front_image")
|
||||
|
||||
|
||||
class HotWordsSerializer(serializers.ModelSerializer):
|
||||
@@ -44,29 +55,4 @@ class HotWordsSerializer(serializers.ModelSerializer):
|
||||
class BannerSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Banner
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
class IndexCategorySerializer(serializers.ModelSerializer):
|
||||
cases = serializers.SerializerMethodField()
|
||||
sub_cat = CategorySerializer2(many=True)
|
||||
ad_cases = serializers.SerializerMethodField()
|
||||
|
||||
def get_ad_cases(self, obj):
|
||||
cases_json = {}
|
||||
ad_cases = IndexAd.objects.filter(category_id=obj.id, )
|
||||
if ad_cases:
|
||||
case_ins = ad_cases[0].cases
|
||||
cases_json = CasesSerializer(case_ins, many=False, context={'request': self.context['request']}).data
|
||||
return cases_json
|
||||
|
||||
|
||||
|
||||
def get_cases(self, obj):
|
||||
all_cases = Cases.objects.filter(Q(category_id=obj.id)|Q(category__parent_category_id=obj.id)|Q(category__parent_category__parent_category_id=obj.id))
|
||||
cases_serializer = CasesSerializer(all_cases, many=True, context={'request': self.context['request']})
|
||||
return cases_serializer.data
|
||||
|
||||
class Meta:
|
||||
model = CasesCategory
|
||||
fields = "__all__"
|
||||
fields = "__all__"
|
||||
+15
-18
@@ -1,23 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
__author__ = 'HymanLu'
|
||||
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import mixins
|
||||
from rest_framework import generics
|
||||
from rest_framework import filters
|
||||
from rest_framework.pagination import PageNumberPagination
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.authentication import TokenAuthentication
|
||||
from rest_framework.throttling import UserRateThrottle
|
||||
|
||||
from rest_framework_extensions.cache.mixins import CacheResponseMixin
|
||||
|
||||
from .models import Cases, CasesCategory, HotSearchWords, Banner
|
||||
from .filters import CasesFilter
|
||||
from .serializers import CasesSerializer, CategorySerializer, HotWordsSerializer, BannerSerializer
|
||||
from .serializers import IndexCategorySerializer
|
||||
from rest_framework import status
|
||||
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
|
||||
from rest_framework.permissions import IsAuthenticatedOrReadOnly
|
||||
# Create your views here.
|
||||
|
||||
|
||||
@@ -28,7 +25,7 @@ class CasesPagination(PageNumberPagination):
|
||||
max_page_size = 100
|
||||
|
||||
|
||||
class CasesListViewSet(CacheResponseMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
|
||||
class CasesListViewSet(CacheResponseMixin, mixins.CreateModelMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
|
||||
"""
|
||||
案例列表页, 分页, 搜索, 过滤, 排序
|
||||
"""
|
||||
@@ -36,7 +33,8 @@ class CasesListViewSet(CacheResponseMixin, mixins.ListModelMixin, mixins.Retriev
|
||||
queryset = Cases.objects.all()
|
||||
serializer_class = CasesSerializer
|
||||
pagination_class = CasesPagination
|
||||
# authentication_classes = (TokenAuthentication, )
|
||||
authentication_classes = (JSONWebTokenAuthentication, )
|
||||
permission_classes = (IsAuthenticatedOrReadOnly,)
|
||||
filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
|
||||
filter_class = CasesFilter
|
||||
search_fields = ('name', 'cases_brief', 'cases_desc')
|
||||
@@ -49,6 +47,14 @@ class CasesListViewSet(CacheResponseMixin, mixins.ListModelMixin, mixins.Retriev
|
||||
serializer = self.get_serializer(instance)
|
||||
return Response(serializer.data)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
user = self.perform_create(serializer) # 注册成功,将SQL记录插入语句提交到数据库执行
|
||||
re_dict = serializer.data
|
||||
headers = self.get_success_headers(serializer.data)
|
||||
return Response(re_dict, status=status.HTTP_201_CREATED, headers=headers)
|
||||
|
||||
class CategoryViewset(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet):
|
||||
"""
|
||||
list:
|
||||
@@ -73,13 +79,4 @@ class BannerViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
|
||||
获取案例轮播图列表
|
||||
"""
|
||||
queryset = Banner.objects.all().order_by("index")
|
||||
serializer_class = BannerSerializer
|
||||
|
||||
|
||||
class IndexCategoryViewset(mixins.ListModelMixin, viewsets.GenericViewSet):
|
||||
"""
|
||||
首页案例分类数据
|
||||
"""
|
||||
queryset = CasesCategory.objects.filter(is_tab=True, name__in=["生鲜食品", "酒水饮料"])
|
||||
serializer_class = IndexCategorySerializer
|
||||
|
||||
serializer_class = BannerSerializer
|
||||
@@ -2,13 +2,9 @@
|
||||
__author__ = 'HymanLu'
|
||||
|
||||
import xadmin
|
||||
from .models import UserFav, UserLeavingMessage
|
||||
from .models import UserFav
|
||||
|
||||
class UserFavAdmin(object):
|
||||
list_display = ['user', 'goods', "add_time"]
|
||||
|
||||
class UserLeavingMessageAdmin(object):
|
||||
list_display = ['user', 'message_type', "message", "add_time"]
|
||||
|
||||
xadmin.site.register(UserFav, UserFavAdmin)
|
||||
xadmin.site.register(UserLeavingMessage, UserLeavingMessageAdmin)
|
||||
xadmin.site.register(UserFav, UserFavAdmin)
|
||||
@@ -0,0 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.7 on 2017-11-14 17:39
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('user_operation', '0002_auto_20171021_2051'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='userleavingmessage',
|
||||
name='user',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='UserLeavingMessage',
|
||||
),
|
||||
]
|
||||
@@ -25,31 +25,4 @@ class UserFav(models.Model):
|
||||
unique_together = ("user", "goods")
|
||||
|
||||
def __str__(self):
|
||||
return self.user.username
|
||||
|
||||
|
||||
class UserLeavingMessage(models.Model):
|
||||
"""
|
||||
用户留言
|
||||
"""
|
||||
MESSAGE_CHOICES = (
|
||||
(1, "留言"),
|
||||
(2, "投诉"),
|
||||
(3, "询问"),
|
||||
(4, "售后"),
|
||||
(5, "求购")
|
||||
)
|
||||
user = models.ForeignKey(User, verbose_name="用户")
|
||||
message_type = models.IntegerField(default=1, choices=MESSAGE_CHOICES, verbose_name="留言类型",
|
||||
help_text=u"留言类型: 1(留言),2(投诉),3(询问),4(售后),5(求购)")
|
||||
subject = models.CharField(max_length=100, default="", verbose_name="主题")
|
||||
message = models.TextField(default="", verbose_name="留言内容", help_text="留言内容")
|
||||
file = models.FileField(upload_to="message/images/", verbose_name="上传的文件", help_text="上传的文件")
|
||||
add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")
|
||||
|
||||
class Meta:
|
||||
verbose_name = "用户留言"
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return self.subject
|
||||
return self.user.username
|
||||
@@ -5,7 +5,6 @@ from rest_framework import serializers
|
||||
from rest_framework.validators import UniqueTogetherValidator
|
||||
|
||||
from .models import UserFav
|
||||
from .models import UserLeavingMessage
|
||||
from cases.serializers import CasesSerializer
|
||||
|
||||
|
||||
@@ -32,14 +31,4 @@ class UserFavSerializer(serializers.ModelSerializer):
|
||||
)
|
||||
]
|
||||
|
||||
fields = ("user", "goods", "id")
|
||||
|
||||
|
||||
class LeavingMessageSerializer(serializers.ModelSerializer):
|
||||
user = serializers.HiddenField(
|
||||
default=serializers.CurrentUserDefault()
|
||||
)
|
||||
add_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M')
|
||||
class Meta:
|
||||
model = UserLeavingMessage
|
||||
fields = ("user", "message_type", "subject", "message", "file", "id" ,"add_time")
|
||||
fields = ("user", "goods", "id")
|
||||
@@ -6,10 +6,9 @@ from rest_framework import mixins
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
|
||||
from rest_framework.authentication import SessionAuthentication
|
||||
|
||||
from .models import UserFav, UserLeavingMessage
|
||||
from .models import UserFav
|
||||
from utils.permissions import IsOwnerOrReadOnly
|
||||
from .serializers import UserFavSerializer, UserFavDetailSerializer, LeavingMessageSerializer
|
||||
from .serializers import UserFavSerializer, UserFavDetailSerializer
|
||||
|
||||
|
||||
class UserFavViewset(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin,
|
||||
@@ -41,23 +40,4 @@ class UserFavViewset(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.Retr
|
||||
elif self.action == "create":
|
||||
return UserFavSerializer
|
||||
|
||||
return UserFavSerializer
|
||||
|
||||
|
||||
class LeavingMessageViewset(mixins.ListModelMixin, mixins.DestroyModelMixin, mixins.CreateModelMixin,
|
||||
viewsets.GenericViewSet):
|
||||
"""
|
||||
list:
|
||||
获取用户留言
|
||||
create:
|
||||
添加留言
|
||||
delete:
|
||||
删除留言功能
|
||||
"""
|
||||
|
||||
permission_classes = (IsAuthenticated, IsOwnerOrReadOnly)
|
||||
authentication_classes = (JSONWebTokenAuthentication, SessionAuthentication)
|
||||
serializer_class = LeavingMessageSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return UserLeavingMessage.objects.filter(user=self.request.user)
|
||||
return UserFavSerializer
|
||||
@@ -39,5 +39,4 @@ class SmsVerifyCode(models.Model):
|
||||
return self.code
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
User = get_user_model()
|
||||
|
||||
User = get_user_model(
|
||||
@@ -98,4 +98,4 @@ class UserRegSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ("username", "code", "mobile", "password", "picture_token") # 返回attrs中的这些值作为最终序列化的结果
|
||||
fields = ("username", "code", "mobile", "password", "picture_token") # 返回attrs中的这些值作为最终序列化的结果
|
||||
@@ -22,7 +22,6 @@ from .models import SmsVerifyCode
|
||||
from rest_framework.views import APIView
|
||||
from captcha.models import CaptchaStore
|
||||
from captcha.helpers import captcha_image_url
|
||||
import json
|
||||
|
||||
'''
|
||||
在setting.py文件中指定AUTHENTICATION_BACKENDS为CustomBackend,即可生效
|
||||
@@ -137,8 +136,6 @@ class UserViewset(CreateModelMixin, mixins.UpdateModelMixin, mixins.RetrieveMode
|
||||
payload = jwt_payload_handler(user)
|
||||
re_dict["jwt_token"] = jwt_encode_handler(payload)
|
||||
|
||||
re_dict["name"] = user.name if user.name else user.username
|
||||
|
||||
headers = self.get_success_headers(serializer.data)
|
||||
return Response(re_dict, status=status.HTTP_201_CREATED, headers=headers)
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
__author__ = 'HymanLu'
|
||||
|
||||
from rest_framework.response import Response
|
||||
from rest_framework import status
|
||||
from rest_framework import views
|
||||
import os
|
||||
from APP_Inventor_case_base.settings import REQUEST_HOST
|
||||
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
|
||||
from rest_framework.permissions import IsAuthenticatedOrReadOnly
|
||||
|
||||
class UploadFileView(views.APIView):
|
||||
"""
|
||||
上传文件接口
|
||||
"""
|
||||
authentication_classes = (JSONWebTokenAuthentication,)
|
||||
permission_classes = (IsAuthenticatedOrReadOnly,)
|
||||
dir_name_to_valid_file_extension = {
|
||||
'case_cover_picture': set(['bmp', 'jpg', 'jpeg', 'png', 'gif']),
|
||||
'rich_text_picture': set(['bmp', 'jpg', 'jpeg', 'png', 'gif'])
|
||||
}
|
||||
|
||||
def post(self, request, mediaDir=''):
|
||||
error_reason_dict = {}
|
||||
if len(mediaDir) == 0:
|
||||
error_reason_dict['detail'] = '请传输上传目录的URL参数'
|
||||
return Response(error_reason_dict, status=status.HTTP_400_BAD_REQUEST)
|
||||
if mediaDir not in self.dir_name_to_valid_file_extension:
|
||||
error_reason_dict['detail'] = '请输入合法的上传目录URL参数'
|
||||
return Response(error_reason_dict, status=status.HTTP_400_BAD_REQUEST)
|
||||
file = request.FILES.get('file')
|
||||
fileName = file.name
|
||||
file_extension = os.path.splitext(fileName)[1][1:]
|
||||
if file_extension not in self.dir_name_to_valid_file_extension[mediaDir]:
|
||||
error_reason_dict['detail'] = '不支持该文件类型'
|
||||
return Response(error_reason_dict, status=status.HTTP_400_BAD_REQUEST)
|
||||
baseDir = os.path.dirname(os.path.abspath(__name__))
|
||||
userName = request.user.username
|
||||
localFileDir = os.path.join(baseDir, 'media', mediaDir, userName)
|
||||
if not os.path.exists(localFileDir):
|
||||
os.makedirs(localFileDir)
|
||||
localFileName = os.path.join(localFileDir, fileName)
|
||||
requestURL = REQUEST_HOST + '/media/' + mediaDir + '/' + userName + '/' + fileName
|
||||
with open(localFileName, 'wb') as fout:
|
||||
for chrunk in file.chunks():
|
||||
fout.write(chrunk)
|
||||
return_data = { 'location' : requestURL }
|
||||
|
||||
return Response(return_data, status=status.HTTP_201_CREATED)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 294 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
+253
@@ -0,0 +1,253 @@
|
||||
tinymce.addI18n('zh_CN',{
|
||||
"Redo": "\u91cd\u590d",
|
||||
"Undo": "\u64a4\u6d88",
|
||||
"Cut": "\u526a\u5207",
|
||||
"Copy": "\u590d\u5236",
|
||||
"Paste": "\u7c98\u8d34",
|
||||
"Select all": "\u5168\u9009",
|
||||
"New document": "\u65b0\u6587\u6863",
|
||||
"Ok": "\u786e\u5b9a",
|
||||
"Cancel": "\u53d6\u6d88",
|
||||
"Visual aids": "\u7f51\u683c\u7ebf",
|
||||
"Bold": "\u7c97\u4f53",
|
||||
"Italic": "\u659c\u4f53",
|
||||
"Underline": "\u4e0b\u5212\u7ebf",
|
||||
"Strikethrough": "\u5220\u9664\u7ebf",
|
||||
"Superscript": "\u4e0a\u6807",
|
||||
"Subscript": "\u4e0b\u6807",
|
||||
"Clear formatting": "\u6e05\u9664\u683c\u5f0f",
|
||||
"Align left": "\u5de6\u5bf9\u9f50",
|
||||
"Align center": "\u5c45\u4e2d",
|
||||
"Align right": "\u53f3\u5bf9\u9f50",
|
||||
"Justify": "\u4e24\u7aef\u5bf9\u9f50",
|
||||
"Bullet list": "\u9879\u76ee\u7b26\u53f7",
|
||||
"Numbered list": "\u7f16\u53f7\u5217\u8868",
|
||||
"Decrease indent": "\u51cf\u5c11\u7f29\u8fdb",
|
||||
"Increase indent": "\u589e\u52a0\u7f29\u8fdb",
|
||||
"Close": "\u5173\u95ed",
|
||||
"Formats": "\u683c\u5f0f",
|
||||
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u4f60\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u5bf9\u526a\u8d34\u677f\u7684\u8bbf\u95ee\uff0c\u8bf7\u4f7f\u7528Ctrl+X\/C\/V\u952e\u8fdb\u884c\u590d\u5236\u7c98\u8d34\u3002",
|
||||
"Headers": "\u6807\u9898",
|
||||
"Header 1": "\u6807\u98981",
|
||||
"Header 2": "\u6807\u98982",
|
||||
"Header 3": "\u6807\u98983",
|
||||
"Header 4": "\u6807\u98984",
|
||||
"Header 5": "\u6807\u98985",
|
||||
"Header 6": "\u6807\u98986",
|
||||
"Headings": "\u6807\u9898",
|
||||
"Heading 1": "\u6807\u98981",
|
||||
"Heading 2": "\u6807\u98982",
|
||||
"Heading 3": "\u6807\u98983",
|
||||
"Heading 4": "\u6807\u98984",
|
||||
"Heading 5": "\u6807\u98985",
|
||||
"Heading 6": "\u6807\u98986",
|
||||
"Div": "Div\u533a\u5757",
|
||||
"Pre": "\u9884\u683c\u5f0f\u6587\u672c",
|
||||
"Code": "\u4ee3\u7801",
|
||||
"Paragraph": "\u6bb5\u843d",
|
||||
"Blockquote": "\u5f15\u7528",
|
||||
"Inline": "\u6587\u672c",
|
||||
"Blocks": "\u533a\u5757",
|
||||
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u5f53\u524d\u4e3a\u7eaf\u6587\u672c\u7c98\u8d34\u6a21\u5f0f\uff0c\u518d\u6b21\u70b9\u51fb\u53ef\u4ee5\u56de\u5230\u666e\u901a\u7c98\u8d34\u6a21\u5f0f\u3002",
|
||||
"Font Family": "\u5b57\u4f53",
|
||||
"Font Sizes": "\u5b57\u53f7",
|
||||
"Class": "Class",
|
||||
"Browse for an image": "Browse for an image",
|
||||
"OR": "OR",
|
||||
"Drop an image here": "Drop an image here",
|
||||
"Upload": "\u4e0a\u4f20",
|
||||
"Default": "\u9ed8\u8ba4",
|
||||
"Circle": "\u7a7a\u5fc3\u5706",
|
||||
"Disc": "\u5b9e\u5fc3\u5706",
|
||||
"Square": "\u65b9\u5757",
|
||||
"Lower Alpha": "\u5c0f\u5199\u82f1\u6587\u5b57\u6bcd",
|
||||
"Lower Greek": "\u5c0f\u5199\u5e0c\u814a\u5b57\u6bcd",
|
||||
"Lower Roman": "\u5c0f\u5199\u7f57\u9a6c\u5b57\u6bcd",
|
||||
"Upper Alpha": "\u5927\u5199\u82f1\u6587\u5b57\u6bcd",
|
||||
"Upper Roman": "\u5927\u5199\u7f57\u9a6c\u5b57\u6bcd",
|
||||
"Anchor": "\u951a\u70b9",
|
||||
"Name": "\u540d\u79f0",
|
||||
"Id": "\u6807\u8bc6\u7b26",
|
||||
"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "\u6807\u8bc6\u7b26\u5e94\u8be5\u4ee5\u5b57\u6bcd\u5f00\u5934\uff0c\u540e\u8ddf\u5b57\u6bcd\u3001\u6570\u5b57\u3001\u7834\u6298\u53f7\u3001\u70b9\u3001\u5192\u53f7\u6216\u4e0b\u5212\u7ebf\u3002",
|
||||
"You have unsaved changes are you sure you want to navigate away?": "\u4f60\u8fd8\u6709\u6587\u6863\u5c1a\u672a\u4fdd\u5b58\uff0c\u786e\u5b9a\u8981\u79bb\u5f00\uff1f",
|
||||
"Restore last draft": "\u6062\u590d\u4e0a\u6b21\u7684\u8349\u7a3f",
|
||||
"Special character": "\u7279\u6b8a\u7b26\u53f7",
|
||||
"Source code": "\u6e90\u4ee3\u7801",
|
||||
"Insert\/Edit code sample": "\u63d2\u5165\/\u7f16\u8f91\u4ee3\u7801\u793a\u4f8b",
|
||||
"Language": "\u8bed\u8a00",
|
||||
"Color": "\u989c\u8272",
|
||||
"R": "R",
|
||||
"G": "G",
|
||||
"B": "B",
|
||||
"Left to right": "\u4ece\u5de6\u5230\u53f3",
|
||||
"Right to left": "\u4ece\u53f3\u5230\u5de6",
|
||||
"Emoticons": "\u8868\u60c5",
|
||||
"Document properties": "\u6587\u6863\u5c5e\u6027",
|
||||
"Title": "\u6807\u9898",
|
||||
"Keywords": "\u5173\u952e\u8bcd",
|
||||
"Description": "\u63cf\u8ff0",
|
||||
"Robots": "\u673a\u5668\u4eba",
|
||||
"Author": "\u4f5c\u8005",
|
||||
"Encoding": "\u7f16\u7801",
|
||||
"Fullscreen": "\u5168\u5c4f",
|
||||
"Action": "Action",
|
||||
"Shortcut": "Shortcut",
|
||||
"Help": "Help",
|
||||
"Address": "Address",
|
||||
"Focus to menubar": "Focus to menubar",
|
||||
"Focus to toolbar": "Focus to toolbar",
|
||||
"Focus to element path": "Focus to element path",
|
||||
"Focus to contextual toolbar": "Focus to contextual toolbar",
|
||||
"Insert link (if link plugin activated)": "Insert link (if link plugin activated)",
|
||||
"Save (if save plugin activated)": "Save (if save plugin activated)",
|
||||
"Find (if searchreplace plugin activated)": "Find (if searchreplace plugin activated)",
|
||||
"Plugins installed ({0}):": "Plugins installed ({0}):",
|
||||
"Premium plugins:": "Premium plugins:",
|
||||
"Learn more...": "Learn more...",
|
||||
"You are using {0}": "You are using {0}",
|
||||
"Horizontal line": "\u6c34\u5e73\u5206\u5272\u7ebf",
|
||||
"Insert\/edit image": "\u63d2\u5165\/\u7f16\u8f91\u56fe\u7247",
|
||||
"Image description": "\u56fe\u7247\u63cf\u8ff0",
|
||||
"Source": "\u5730\u5740",
|
||||
"Dimensions": "\u5927\u5c0f",
|
||||
"Constrain proportions": "\u4fdd\u6301\u7eb5\u6a2a\u6bd4",
|
||||
"General": "\u666e\u901a",
|
||||
"Advanced": "\u9ad8\u7ea7",
|
||||
"Style": "\u6837\u5f0f",
|
||||
"Vertical space": "\u5782\u76f4\u8fb9\u8ddd",
|
||||
"Horizontal space": "\u6c34\u5e73\u8fb9\u8ddd",
|
||||
"Border": "\u8fb9\u6846",
|
||||
"Insert image": "\u63d2\u5165\u56fe\u7247",
|
||||
"Image": "\u56fe\u7247",
|
||||
"Image list": "\u56fe\u7247\u5217\u8868",
|
||||
"Rotate counterclockwise": "\u9006\u65f6\u9488\u65cb\u8f6c",
|
||||
"Rotate clockwise": "\u987a\u65f6\u9488\u65cb\u8f6c",
|
||||
"Flip vertically": "\u5782\u76f4\u7ffb\u8f6c",
|
||||
"Flip horizontally": "\u6c34\u5e73\u7ffb\u8f6c",
|
||||
"Edit image": "\u7f16\u8f91\u56fe\u7247",
|
||||
"Image options": "\u56fe\u7247\u9009\u9879",
|
||||
"Zoom in": "\u653e\u5927",
|
||||
"Zoom out": "\u7f29\u5c0f",
|
||||
"Crop": "\u88c1\u526a",
|
||||
"Resize": "\u8c03\u6574\u5927\u5c0f",
|
||||
"Orientation": "\u65b9\u5411",
|
||||
"Brightness": "\u4eae\u5ea6",
|
||||
"Sharpen": "\u9510\u5316",
|
||||
"Contrast": "\u5bf9\u6bd4\u5ea6",
|
||||
"Color levels": "\u989c\u8272\u5c42\u6b21",
|
||||
"Gamma": "\u4f3d\u9a6c\u503c",
|
||||
"Invert": "\u53cd\u8f6c",
|
||||
"Apply": "\u5e94\u7528",
|
||||
"Back": "\u540e\u9000",
|
||||
"Insert date\/time": "\u63d2\u5165\u65e5\u671f\/\u65f6\u95f4",
|
||||
"Date\/time": "\u65e5\u671f\/\u65f6\u95f4",
|
||||
"Insert link": "\u63d2\u5165\u94fe\u63a5",
|
||||
"Insert\/edit link": "\u63d2\u5165\/\u7f16\u8f91\u94fe\u63a5",
|
||||
"Text to display": "\u663e\u793a\u6587\u5b57",
|
||||
"Url": "\u5730\u5740",
|
||||
"Target": "\u6253\u5f00\u65b9\u5f0f",
|
||||
"None": "\u65e0",
|
||||
"New window": "\u5728\u65b0\u7a97\u53e3\u6253\u5f00",
|
||||
"Remove link": "\u5220\u9664\u94fe\u63a5",
|
||||
"Anchors": "\u951a\u70b9",
|
||||
"Link": "\u94fe\u63a5",
|
||||
"Paste or type a link": "\u7c98\u8d34\u6216\u8f93\u5165\u94fe\u63a5",
|
||||
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u4e3a\u90ae\u4ef6\u5730\u5740\uff0c\u9700\u8981\u52a0\u4e0amailto:\u524d\u7f00\u5417\uff1f",
|
||||
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u4f60\u6240\u586b\u5199\u7684URL\u5730\u5740\u5c5e\u4e8e\u5916\u90e8\u94fe\u63a5\uff0c\u9700\u8981\u52a0\u4e0ahttp:\/\/:\u524d\u7f00\u5417\uff1f",
|
||||
"Link list": "Link list",
|
||||
"Insert video": "\u63d2\u5165\u89c6\u9891",
|
||||
"Insert\/edit video": "\u63d2\u5165\/\u7f16\u8f91\u89c6\u9891",
|
||||
"Insert\/edit media": "\u63d2\u5165\/\u7f16\u8f91\u5a92\u4f53",
|
||||
"Alternative source": "\u955c\u50cf",
|
||||
"Poster": "\u5c01\u9762",
|
||||
"Paste your embed code below:": "\u5c06\u5185\u5d4c\u4ee3\u7801\u7c98\u8d34\u5728\u4e0b\u9762:",
|
||||
"Embed": "\u5185\u5d4c",
|
||||
"Media": "\u5a92\u4f53",
|
||||
"Nonbreaking space": "\u4e0d\u95f4\u65ad\u7a7a\u683c",
|
||||
"Page break": "\u5206\u9875\u7b26",
|
||||
"Paste as text": "\u7c98\u8d34\u4e3a\u6587\u672c",
|
||||
"Preview": "\u9884\u89c8",
|
||||
"Print": "\u6253\u5370",
|
||||
"Save": "\u4fdd\u5b58",
|
||||
"Find": "\u67e5\u627e",
|
||||
"Replace with": "\u66ff\u6362\u4e3a",
|
||||
"Replace": "\u66ff\u6362",
|
||||
"Replace all": "\u5168\u90e8\u66ff\u6362",
|
||||
"Prev": "\u4e0a\u4e00\u4e2a",
|
||||
"Next": "\u4e0b\u4e00\u4e2a",
|
||||
"Find and replace": "\u67e5\u627e\u548c\u66ff\u6362",
|
||||
"Could not find the specified string.": "\u672a\u627e\u5230\u641c\u7d22\u5185\u5bb9.",
|
||||
"Match case": "\u533a\u5206\u5927\u5c0f\u5199",
|
||||
"Whole words": "\u5168\u5b57\u5339\u914d",
|
||||
"Spellcheck": "\u62fc\u5199\u68c0\u67e5",
|
||||
"Ignore": "\u5ffd\u7565",
|
||||
"Ignore all": "\u5168\u90e8\u5ffd\u7565",
|
||||
"Finish": "\u5b8c\u6210",
|
||||
"Add to Dictionary": "\u6dfb\u52a0\u5230\u5b57\u5178",
|
||||
"Insert table": "\u63d2\u5165\u8868\u683c",
|
||||
"Table properties": "\u8868\u683c\u5c5e\u6027",
|
||||
"Delete table": "\u5220\u9664\u8868\u683c",
|
||||
"Cell": "\u5355\u5143\u683c",
|
||||
"Row": "\u884c",
|
||||
"Column": "\u5217",
|
||||
"Cell properties": "\u5355\u5143\u683c\u5c5e\u6027",
|
||||
"Merge cells": "\u5408\u5e76\u5355\u5143\u683c",
|
||||
"Split cell": "\u62c6\u5206\u5355\u5143\u683c",
|
||||
"Insert row before": "\u5728\u4e0a\u65b9\u63d2\u5165",
|
||||
"Insert row after": "\u5728\u4e0b\u65b9\u63d2\u5165",
|
||||
"Delete row": "\u5220\u9664\u884c",
|
||||
"Row properties": "\u884c\u5c5e\u6027",
|
||||
"Cut row": "\u526a\u5207\u884c",
|
||||
"Copy row": "\u590d\u5236\u884c",
|
||||
"Paste row before": "\u7c98\u8d34\u5230\u4e0a\u65b9",
|
||||
"Paste row after": "\u7c98\u8d34\u5230\u4e0b\u65b9",
|
||||
"Insert column before": "\u5728\u5de6\u4fa7\u63d2\u5165",
|
||||
"Insert column after": "\u5728\u53f3\u4fa7\u63d2\u5165",
|
||||
"Delete column": "\u5220\u9664\u5217",
|
||||
"Cols": "\u5217",
|
||||
"Rows": "\u884c",
|
||||
"Width": "\u5bbd",
|
||||
"Height": "\u9ad8",
|
||||
"Cell spacing": "\u5355\u5143\u683c\u5916\u95f4\u8ddd",
|
||||
"Cell padding": "\u5355\u5143\u683c\u5185\u8fb9\u8ddd",
|
||||
"Caption": "\u6807\u9898",
|
||||
"Left": "\u5de6\u5bf9\u9f50",
|
||||
"Center": "\u5c45\u4e2d",
|
||||
"Right": "\u53f3\u5bf9\u9f50",
|
||||
"Cell type": "\u5355\u5143\u683c\u7c7b\u578b",
|
||||
"Scope": "\u8303\u56f4",
|
||||
"Alignment": "\u5bf9\u9f50\u65b9\u5f0f",
|
||||
"H Align": "\u6c34\u5e73\u5bf9\u9f50",
|
||||
"V Align": "\u5782\u76f4\u5bf9\u9f50",
|
||||
"Top": "\u9876\u90e8\u5bf9\u9f50",
|
||||
"Middle": "\u5782\u76f4\u5c45\u4e2d",
|
||||
"Bottom": "\u5e95\u90e8\u5bf9\u9f50",
|
||||
"Header cell": "\u8868\u5934\u5355\u5143\u683c",
|
||||
"Row group": "\u884c\u7ec4",
|
||||
"Column group": "\u5217\u7ec4",
|
||||
"Row type": "\u884c\u7c7b\u578b",
|
||||
"Header": "\u8868\u5934",
|
||||
"Body": "\u8868\u4f53",
|
||||
"Footer": "\u8868\u5c3e",
|
||||
"Border color": "\u8fb9\u6846\u989c\u8272",
|
||||
"Insert template": "\u63d2\u5165\u6a21\u677f",
|
||||
"Templates": "\u6a21\u677f",
|
||||
"Template": "Template",
|
||||
"Text color": "\u6587\u5b57\u989c\u8272",
|
||||
"Background color": "\u80cc\u666f\u8272",
|
||||
"Custom...": "\u81ea\u5b9a\u4e49...",
|
||||
"Custom color": "\u81ea\u5b9a\u4e49\u989c\u8272",
|
||||
"No color": "\u65e0",
|
||||
"Table of Contents": "\u5185\u5bb9\u5217\u8868",
|
||||
"Show blocks": "\u663e\u793a\u533a\u5757\u8fb9\u6846",
|
||||
"Show invisible characters": "\u663e\u793a\u4e0d\u53ef\u89c1\u5b57\u7b26",
|
||||
"Words: {0}": "\u5b57\u6570\uff1a{0}",
|
||||
"File": "\u6587\u4ef6",
|
||||
"Edit": "\u7f16\u8f91",
|
||||
"Insert": "\u63d2\u5165",
|
||||
"View": "\u89c6\u56fe",
|
||||
"Format": "\u683c\u5f0f",
|
||||
"Table": "\u8868\u683c",
|
||||
"Tools": "\u5de5\u5177",
|
||||
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u5728\u7f16\u8f91\u533a\u6309ALT-F9\u6253\u5f00\u83dc\u5355\uff0c\u6309ALT-F10\u6253\u5f00\u5de5\u5177\u680f\uff0c\u6309ALT-0\u67e5\u770b\u5e2e\u52a9"
|
||||
});
|
||||
Reference in New Issue
Block a user