完成几个页面
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
package net.alawn.bill.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 16:53 2019-05-17
|
||||
*/
|
||||
//@Configuration
|
||||
public class WebMvcConfig implements WebMvcConfigurer {
|
||||
|
||||
// public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
// registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
// registry.addMapping("/basic/**")
|
||||
// .allowedOrigins("http://domain2.com")
|
||||
// .allowedMethods("GET","POST","PUT", "DELETE")
|
||||
// .allowedHeaders("header1", "header2", "header3")
|
||||
// .exposedHeaders("header1", "header2")
|
||||
// .allowCredentials(false).maxAge(3600);
|
||||
registry.addMapping("/**")
|
||||
.allowedOrigins("*")
|
||||
.allowedMethods("PUT", "DELETE", "GET", "POST", "OPTIONS")
|
||||
.allowedHeaders("*")
|
||||
.exposedHeaders("access-control-allow-headers",
|
||||
"access-control-allow-methods",
|
||||
"access-control-allow-origin",
|
||||
"access-control-max-age",
|
||||
"X-Frame-Options")
|
||||
.allowCredentials(true).maxAge(3600);
|
||||
}
|
||||
|
||||
}
|
||||
+32
-1
@@ -1,5 +1,7 @@
|
||||
package net.alawn.bill.security;
|
||||
package net.alawn.bill.config;
|
||||
|
||||
import net.alawn.bill.security.JwtAuthenticationEntryPoint;
|
||||
import net.alawn.bill.security.JwtAuthenticationTokenFilter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -21,6 +23,11 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
|
||||
import org.springframework.security.web.firewall.HttpFirewall;
|
||||
import org.springframework.security.web.firewall.StrictHttpFirewall;
|
||||
import org.springframework.util.DigestUtils;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
@@ -78,7 +85,10 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
/** Security Http 配置 */
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// http // 去掉跨域
|
||||
http.csrf().disable() // 去掉跨域
|
||||
.cors()
|
||||
.and()
|
||||
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
@@ -86,6 +96,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
.antMatchers("/druid/**").permitAll()
|
||||
.antMatchers("/swagger*").permitAll()
|
||||
.antMatchers( HttpMethod.GET, "/","/*.html", "/favicon.ico", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
|
||||
// .antMatchers("/resources/**").permitAll()
|
||||
.antMatchers("/auth/**").permitAll()
|
||||
.antMatchers("/bill/**").authenticated()
|
||||
.antMatchers("/basic/**/*").authenticated()
|
||||
@@ -104,6 +115,26 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
http.headers().cacheControl(); // 禁用缓存
|
||||
}
|
||||
|
||||
/** Security 跨域设置 */
|
||||
@Bean
|
||||
CorsConfigurationSource corsConfigurationSource() {
|
||||
CorsConfiguration configuration = new CorsConfiguration();
|
||||
configuration.setAllowedOrigins(Arrays.asList("*"));
|
||||
configuration.setAllowedMethods(Arrays.asList("PUT", "DELETE", "GET", "POST", "OPTIONS"));
|
||||
configuration.setAllowedHeaders(Arrays.asList("*"));
|
||||
configuration.addExposedHeader("Location"); // 暴露 Location header
|
||||
configuration.addExposedHeader("access-control-allow-headers");
|
||||
configuration.addExposedHeader("access-control-allow-methods");
|
||||
configuration.addExposedHeader("access-control-allow-origin");
|
||||
configuration.addExposedHeader("access-control-max-age");
|
||||
configuration.addExposedHeader("X-Frame-Options");
|
||||
configuration.setAllowCredentials(true);
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
source.registerCorsConfiguration("/**", configuration);
|
||||
return source;
|
||||
}
|
||||
|
||||
|
||||
/** Security Web 配置 */
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
@@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.Principal;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
@@ -47,7 +48,7 @@ public class BasicController {
|
||||
@Autowired
|
||||
TitleRepo titleRepo;
|
||||
|
||||
@RequestMapping(value = "/post",method = RequestMethod.POST)
|
||||
@RequestMapping(value = "/posts",method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public ResponseEntity<Post> addPost(@RequestBody AddPost addPost, Principal principal) throws URISyntaxException {
|
||||
AuthUser authUser = (AuthUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
@@ -61,7 +62,17 @@ public class BasicController {
|
||||
return ResponseEntity.ok(post);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/post/{id}",method = RequestMethod.GET)
|
||||
@RequestMapping(value = "/posts",method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public ResponseEntity<List<Post>> fetchPosts() {
|
||||
AuthUser authUser = (AuthUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
long userId = authUser.getId();
|
||||
|
||||
List<Post> posts = postRepo.findByUserId(userId);
|
||||
return ResponseEntity.ok(posts);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/posts/{id}",method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public ResponseEntity<Post> getPost(@PathVariable long id){
|
||||
log.info("post id:" + id);
|
||||
@@ -78,7 +89,7 @@ public class BasicController {
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping(value = "/merchant",method = RequestMethod.POST)
|
||||
@RequestMapping(value = "/merchants",method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public ResponseEntity<Merchant> addMerchant(@RequestBody AddMerchant addMerchant) throws URISyntaxException {
|
||||
/** 登记 Post */
|
||||
@@ -87,7 +98,15 @@ public class BasicController {
|
||||
return ResponseEntity.ok(merchant);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/merchant/{id}",method = RequestMethod.GET)
|
||||
@RequestMapping(value = "/merchants",method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public ResponseEntity<List<Merchant>> fetchMerchants() throws URISyntaxException {
|
||||
List<Merchant> merchants = merchantRepo.findAll();
|
||||
return ResponseEntity.ok(merchants);
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping(value = "/merchants/{id}",method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public ResponseEntity<Merchant> getMerchant(@PathVariable long id){
|
||||
/** 登记 Post */
|
||||
@@ -100,21 +119,26 @@ public class BasicController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@RequestMapping(value = "/title",method = RequestMethod.POST)
|
||||
@RequestMapping(value = "/titles",method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public ResponseEntity<Title> addTitle(@RequestBody AddTitle addTitle) throws URISyntaxException {
|
||||
/** 登记 Post */
|
||||
public ResponseEntity<Title> addTitle(@RequestBody AddTitle addTitle) {
|
||||
/** 登记 Title */
|
||||
Title title = titleRepo.save(addTitle.build());
|
||||
titleRepo.flush();
|
||||
return ResponseEntity.ok(title);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/title/{id}",method = RequestMethod.GET)
|
||||
@RequestMapping(value = "/titles",method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public ResponseEntity<List<Title>> addTitle() {
|
||||
List<Title> titles = titleRepo.findAll();
|
||||
return ResponseEntity.ok(titles);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/titles/{id}",method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public ResponseEntity<Title> getTitle(@PathVariable long id){
|
||||
/** 登记 Post */
|
||||
/** 登记 Title */
|
||||
Optional<Title> title = titleRepo.findById(id);
|
||||
if(title.isPresent()) {
|
||||
return ResponseEntity.ok(title.get());
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.alawn.bill.entity.po;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.Column;
|
||||
@@ -20,6 +21,7 @@ import javax.persistence.Table;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Post extends Base{
|
||||
@JsonIgnore
|
||||
private long userId ;
|
||||
private String address ;
|
||||
private String contact ;
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package net.alawn.bill.exception;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 15:52 2019-03-28
|
||||
*/
|
||||
|
||||
public class UserAlreadyExistException extends CommonException {
|
||||
|
||||
private final static RespMsg msg = RespMsg.USER_ALREADY_EXIST;
|
||||
|
||||
public UserAlreadyExistException() {
|
||||
super(msg.code(),msg.message());
|
||||
}
|
||||
|
||||
public UserAlreadyExistException(String message) {
|
||||
super(msg.code(),message);
|
||||
}
|
||||
|
||||
public UserAlreadyExistException(String format, Object... arguments) {
|
||||
super(msg.code(),format, arguments);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package net.alawn.bill.repository;
|
||||
|
||||
import net.alawn.bill.entity.po.Book;
|
||||
import net.alawn.bill.entity.po.Item;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@@ -5,6 +5,8 @@ import net.alawn.bill.entity.po.Merchant;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
@@ -13,5 +15,4 @@ import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface MerchantRepo extends JpaRepository<Merchant, Long> {
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import net.alawn.bill.entity.po.Post;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
@@ -13,5 +15,5 @@ import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface PostRepo extends JpaRepository<Post, Long> {
|
||||
|
||||
List<Post> findByUserId(long userId);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,8 @@ server.port= 30000
|
||||
# JWT
|
||||
jwt.header=Authorization
|
||||
jwt.secret=8UbBmq9LNnPKFc4sFN7ZF2TTCGbCXTsy
|
||||
jwt.expiration=604800
|
||||
jwt.expiration=999604800
|
||||
#jwt.expiration=604800
|
||||
jwt.tokenHead=Bearer
|
||||
jwt.route.authentication.path=auth
|
||||
jwt.route.authentication.refresh=refresh
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"presets": [
|
||||
["env", {
|
||||
"modules": false,
|
||||
"targets": {
|
||||
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
|
||||
}
|
||||
}],
|
||||
"stage-2"
|
||||
],
|
||||
"plugins": ["transform-vue-jsx", "transform-runtime"],
|
||||
"env": {
|
||||
"test": {
|
||||
"presets": ["env", "stage-2"],
|
||||
"plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
@@ -0,0 +1,5 @@
|
||||
/build/
|
||||
/config/
|
||||
/dist/
|
||||
/*.js
|
||||
/test/unit/coverage/
|
||||
@@ -0,0 +1,29 @@
|
||||
// https://eslint.org/docs/user-guide/configuring
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint'
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
},
|
||||
extends: [
|
||||
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
|
||||
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
|
||||
'plugin:vue/essential',
|
||||
// https://github.com/standard/standard/blob/master/docs/RULES-en.md
|
||||
'standard'
|
||||
],
|
||||
// required to lint *.vue files
|
||||
plugins: [
|
||||
'vue'
|
||||
],
|
||||
// add your custom rules here
|
||||
rules: {
|
||||
// allow async-await
|
||||
'generator-star-spacing': 'off',
|
||||
// allow debugger during development
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
/dist/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
/test/unit/coverage/
|
||||
/test/e2e/reports/
|
||||
selenium-debug.log
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
@@ -0,0 +1,10 @@
|
||||
// https://github.com/michael-ciniawsky/postcss-load-config
|
||||
|
||||
module.exports = {
|
||||
"plugins": {
|
||||
"postcss-import": {},
|
||||
"postcss-url": {},
|
||||
// to edit target browsers: use "browserslist" field in package.json
|
||||
"autoprefixer": {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
# bill
|
||||
|
||||
> bill
|
||||
|
||||
## Build Setup
|
||||
|
||||
``` bash
|
||||
# install dependencies
|
||||
npm install
|
||||
|
||||
# serve with hot reload at localhost:8080
|
||||
npm run dev
|
||||
|
||||
# build for production with minification
|
||||
npm run build
|
||||
|
||||
# build for production and view the bundle analyzer report
|
||||
npm run build --report
|
||||
|
||||
# run unit tests
|
||||
npm run unit
|
||||
|
||||
# run e2e tests
|
||||
npm run e2e
|
||||
|
||||
# run all tests
|
||||
npm test
|
||||
```
|
||||
|
||||
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
|
||||
@@ -0,0 +1,7 @@
|
||||
'use strict'
|
||||
const merge = require('webpack-merge')
|
||||
const prodEnv = require('./prod.env')
|
||||
|
||||
module.exports = merge(prodEnv, {
|
||||
NODE_ENV: '"development"'
|
||||
})
|
||||
@@ -0,0 +1,76 @@
|
||||
'use strict'
|
||||
// Template version: 1.3.1
|
||||
// see http://vuejs-templates.github.io/webpack for documentation.
|
||||
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
dev: {
|
||||
|
||||
// Paths
|
||||
assetsSubDirectory: 'static',
|
||||
assetsPublicPath: '/',
|
||||
proxyTable: {},
|
||||
|
||||
// Various Dev Server settings
|
||||
host: 'localhost', // can be overwritten by process.env.HOST
|
||||
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
|
||||
autoOpenBrowser: false,
|
||||
errorOverlay: true,
|
||||
notifyOnErrors: true,
|
||||
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
|
||||
|
||||
// Use Eslint Loader?
|
||||
// If true, your code will be linted during bundling and
|
||||
// linting errors and warnings will be shown in the console.
|
||||
useEslint: true,
|
||||
// If true, eslint errors and warnings will also be shown in the error overlay
|
||||
// in the browser.
|
||||
showEslintErrorsInOverlay: false,
|
||||
|
||||
/**
|
||||
* Source Maps
|
||||
*/
|
||||
|
||||
// https://webpack.js.org/configuration/devtool/#development
|
||||
devtool: 'cheap-module-eval-source-map',
|
||||
|
||||
// If you have problems debugging vue-files in devtools,
|
||||
// set this to false - it *may* help
|
||||
// https://vue-loader.vuejs.org/en/options.html#cachebusting
|
||||
cacheBusting: true,
|
||||
|
||||
cssSourceMap: true
|
||||
},
|
||||
|
||||
build: {
|
||||
// Template for index.html
|
||||
index: path.resolve(__dirname, '../dist/index.html'),
|
||||
|
||||
// Paths
|
||||
assetsRoot: path.resolve(__dirname, '../dist'),
|
||||
assetsSubDirectory: 'static',
|
||||
assetsPublicPath: '/',
|
||||
|
||||
/**
|
||||
* Source Maps
|
||||
*/
|
||||
|
||||
productionSourceMap: true,
|
||||
// https://webpack.js.org/configuration/devtool/#production
|
||||
devtool: '#source-map',
|
||||
|
||||
// Gzip off by default as many popular static hosts such as
|
||||
// Surge or Netlify already gzip all static assets for you.
|
||||
// Before setting to `true`, make sure to:
|
||||
// npm install --save-dev compression-webpack-plugin
|
||||
productionGzip: false,
|
||||
productionGzipExtensions: ['js', 'css'],
|
||||
|
||||
// Run the build command with an extra argument to
|
||||
// View the bundle analyzer report after build finishes:
|
||||
// `npm run build --report`
|
||||
// Set to `true` or `false` to always turn it on or off
|
||||
bundleAnalyzerReport: process.env.npm_config_report
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
'use strict'
|
||||
module.exports = {
|
||||
NODE_ENV: '"production"'
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
'use strict'
|
||||
const merge = require('webpack-merge')
|
||||
const devEnv = require('./dev.env')
|
||||
|
||||
module.exports = merge(devEnv, {
|
||||
NODE_ENV: '"testing"'
|
||||
})
|
||||
@@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title>bill</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
Generated
+16235
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"name": "bill",
|
||||
"version": "1.0.0",
|
||||
"description": "bill",
|
||||
"author": "alawn.cn@gmail.com",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
|
||||
"start": "npm run dev",
|
||||
"unit": "jest --config test/unit/jest.conf.js --coverage",
|
||||
"e2e": "node test/e2e/runner.js",
|
||||
"test": "npm run unit && npm run e2e",
|
||||
"lint": "eslint --ext .js,.vue src test/unit test/e2e/specs",
|
||||
"build": "node build/build.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.18.0",
|
||||
"element-ui": "^2.8.2",
|
||||
"vue": "^2.5.2",
|
||||
"vue-router": "^3.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^7.1.2",
|
||||
"babel-core": "^6.22.1",
|
||||
"babel-eslint": "^8.2.1",
|
||||
"babel-helper-vue-jsx-merge-props": "^2.0.3",
|
||||
"babel-jest": "^24.8.0",
|
||||
"babel-loader": "^7.1.1",
|
||||
"babel-plugin-dynamic-import-node": "^1.2.0",
|
||||
"babel-plugin-syntax-jsx": "^6.18.0",
|
||||
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
|
||||
"babel-plugin-transform-runtime": "^6.22.0",
|
||||
"babel-plugin-transform-vue-jsx": "^3.5.0",
|
||||
"babel-preset-env": "^1.3.2",
|
||||
"babel-preset-stage-2": "^6.22.0",
|
||||
"babel-register": "^6.22.0",
|
||||
"chalk": "^2.0.1",
|
||||
"chromedriver": "^2.27.2",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"cross-spawn": "^5.0.1",
|
||||
"css-loader": "^2.1.1",
|
||||
"eslint": "^4.15.0",
|
||||
"eslint-config-standard": "^10.2.1",
|
||||
"eslint-friendly-formatter": "^3.0.0",
|
||||
"eslint-loader": "^1.7.1",
|
||||
"eslint-plugin-import": "^2.7.0",
|
||||
"eslint-plugin-node": "^5.2.0",
|
||||
"eslint-plugin-promise": "^3.4.0",
|
||||
"eslint-plugin-standard": "^3.0.1",
|
||||
"eslint-plugin-vue": "^4.0.0",
|
||||
"extract-text-webpack-plugin": "^3.0.0",
|
||||
"file-loader": "^1.1.4",
|
||||
"friendly-errors-webpack-plugin": "^1.6.1",
|
||||
"html-webpack-plugin": "^2.30.1",
|
||||
"jest": "^24.8.0",
|
||||
"jest-serializer-vue": "^0.3.0",
|
||||
"nightwatch": "^1.1.11",
|
||||
"node-notifier": "^5.1.2",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.1",
|
||||
"ora": "^1.2.0",
|
||||
"portfinder": "^1.0.13",
|
||||
"postcss-import": "^11.0.0",
|
||||
"postcss-loader": "^2.0.8",
|
||||
"postcss-url": "^7.2.1",
|
||||
"rimraf": "^2.6.0",
|
||||
"selenium-server": "^3.0.1",
|
||||
"semver": "^5.3.0",
|
||||
"shelljs": "^0.7.6",
|
||||
"uglifyjs-webpack-plugin": "^1.1.1",
|
||||
"url-loader": "^1.1.2",
|
||||
"vue-jest": "^1.0.2",
|
||||
"vue-loader": "^13.3.0",
|
||||
"vue-style-loader": "^3.0.1",
|
||||
"vue-template-compiler": "^2.5.2",
|
||||
"webpack": "^3.6.0",
|
||||
"webpack-bundle-analyzer": "^3.3.2",
|
||||
"webpack-dev-server": "^2.9.1",
|
||||
"webpack-merge": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not ie <= 8"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<!-- <img src="./assets/logo.png"> -->
|
||||
<router-view/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'App'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#app {
|
||||
font-family: 'Avenir', Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-align: center;
|
||||
color: #2c3e50;
|
||||
margin-top: 60px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,31 @@
|
||||
import HttpRequest from '@/axios/api.request'
|
||||
|
||||
HttpRequest.interceptors.request.use(
|
||||
config => {
|
||||
// if (localStorage.token) { //判断token是否存在
|
||||
// config.headers.Authorization = localStorage.token; //将token设置成请求头
|
||||
// }
|
||||
config.headers.Authorization = "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhbGF3biIsImNyZWF0ZWQiOjE1NTg2ODY4MTk0NjcsImlhdCI6MTU1ODY4NjgxOSwiZXhwIjoxNTU5MjkxNjE5fQ.N9ZSMrStIaUyngSpvmup_akXQaueLSIX5-h4Q_fixdM"; //将token设置成请求头
|
||||
|
||||
|
||||
return config;
|
||||
},
|
||||
err => {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
);
|
||||
|
||||
export const MerchantAddAction = (merc) => {
|
||||
return HttpRequest.request({
|
||||
url:'basic/merchant',
|
||||
method: 'post',
|
||||
data: merc
|
||||
})
|
||||
}
|
||||
|
||||
export const MerchantGetAction = (id) => {
|
||||
return HttpRequest.request({
|
||||
url: 'basic/merchant/' + id,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import HttpRequest from '@/axios/api.request'
|
||||
|
||||
export const addMerchant = (merc) => {
|
||||
return HttpRequest.request({
|
||||
url: 'basic/merchants',
|
||||
method: 'post',
|
||||
data: merc
|
||||
})
|
||||
}
|
||||
|
||||
export const fetchMerchants = () => {
|
||||
return HttpRequest.request({
|
||||
url: 'basic/merchants',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
export const fetchTitles = () => {
|
||||
return HttpRequest.request({
|
||||
url: 'basic/titles',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
export const getMerchant = (id) => {
|
||||
return HttpRequest.request({
|
||||
url: 'basic/merchants/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export const addPost = (merc) => {
|
||||
return HttpRequest.request({
|
||||
url: 'basic/posts',
|
||||
method: 'post',
|
||||
data: merc
|
||||
})
|
||||
}
|
||||
|
||||
export const fetchPosts = () => {
|
||||
return HttpRequest.request({
|
||||
url: 'basic/posts',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export const getPost = (id) => {
|
||||
return HttpRequest.request({
|
||||
url: 'basic/posts/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export const newBill = (bill) => {
|
||||
return HttpRequest.request({
|
||||
url: 'bills/',
|
||||
method: 'post',
|
||||
data: bill
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import HttpRequest from '@/axios/api.request'
|
||||
|
||||
export const UserLoginAction = (ruleForm) => {
|
||||
return HttpRequest.request({
|
||||
url: 'auth',
|
||||
method: 'post',
|
||||
data: ruleForm
|
||||
})
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
@@ -0,0 +1,11 @@
|
||||
import axios from 'axios'
|
||||
import config from './index'
|
||||
const baseUrl = process.env.NODE_ENV === 'development' ? config.baseUrl.dev : config.baseUrl.pro
|
||||
|
||||
const HttpRequest = axios.create({
|
||||
// api的base_url
|
||||
baseURL: baseUrl,
|
||||
// 请求超时时间
|
||||
timeout: 5000
|
||||
})
|
||||
export default HttpRequest
|
||||
@@ -0,0 +1,10 @@
|
||||
export default {
|
||||
/**
|
||||
* @description api请求基础路径
|
||||
*/
|
||||
baseUrl: {
|
||||
dev: 'http://localhost:30000/',
|
||||
pro: 'http://localhost:30000/'
|
||||
// pro: 'http://101.132.124.171:8080/demo-1.0/api/'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<div class="hello">
|
||||
<h1>{{ msg }}</h1>
|
||||
<h2>Essential Links</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
href="https://vuejs.org"
|
||||
target="_blank"
|
||||
>
|
||||
Core Docs
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://forum.vuejs.org"
|
||||
target="_blank"
|
||||
>
|
||||
Forum
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://chat.vuejs.org"
|
||||
target="_blank"
|
||||
>
|
||||
Community Chat
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://twitter.com/vuejs"
|
||||
target="_blank"
|
||||
>
|
||||
Twitter
|
||||
</a>
|
||||
</li>
|
||||
<br>
|
||||
<li>
|
||||
<a
|
||||
href="http://vuejs-templates.github.io/webpack/"
|
||||
target="_blank"
|
||||
>
|
||||
Docs for This Template
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h2>Ecosystem</h2>
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
href="http://router.vuejs.org/"
|
||||
target="_blank"
|
||||
>
|
||||
vue-router
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="http://vuex.vuejs.org/"
|
||||
target="_blank"
|
||||
>
|
||||
vuex
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="http://vue-loader.vuejs.org/"
|
||||
target="_blank"
|
||||
>
|
||||
vue-loader
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/awesome-vue"
|
||||
target="_blank"
|
||||
>
|
||||
awesome-vue
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'HelloWorld',
|
||||
data () {
|
||||
return {
|
||||
msg: 'Welcome to Your Vue.js App'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h1, h2 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,34 @@
|
||||
// The Vue build version to load with the `import` command
|
||||
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
|
||||
import Vue from 'vue'
|
||||
import App from './App'
|
||||
import router from './router'
|
||||
import ElementUI from 'element-ui'
|
||||
import 'element-ui/lib/theme-chalk/index.css'
|
||||
import HttpRequest from '@/axios/api.request'
|
||||
|
||||
Vue.use(ElementUI)
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
HttpRequest.interceptors.request.use(
|
||||
config => {
|
||||
// 判断token是否存在
|
||||
if (localStorage.token) {
|
||||
// 将token设置成请求头
|
||||
config.headers.Authorization = localStorage.token
|
||||
}
|
||||
// config.headers.Authorization = "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhbGF3biIsImNyZWF0ZWQiOjE1NTg2ODY4MTk0NjcsImlhdCI6MTU1ODY4NjgxOSwiZXhwIjoxNTU5MjkxNjE5fQ.N9ZSMrStIaUyngSpvmup_akXQaueLSIX5-h4Q_fixdM" //将token设置成请求头
|
||||
return config
|
||||
}, function(err) {
|
||||
return Promise.reject(err)
|
||||
}
|
||||
)
|
||||
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
el: '#app',
|
||||
router,
|
||||
components: { App },
|
||||
template: '<App/>'
|
||||
})
|
||||
@@ -0,0 +1,30 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import HelloWorld from '@/components/HelloWorld'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
export default new Router({
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'HelloWorld',
|
||||
component: HelloWorld
|
||||
},
|
||||
{
|
||||
path: '/merchant',
|
||||
name: 'Merchant',
|
||||
component: () => import(/* webpackChunkName: "merchant" */ '../views/Merchant.vue')
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'Login',
|
||||
component: () => import(/* webpackChunkName: "merchant" */ '../views/Login.vue')
|
||||
},
|
||||
{
|
||||
path: '/bill',
|
||||
name: 'Bill',
|
||||
component: () => import(/* webpackChunkName: "merchant" */ '../views/Bill.vue')
|
||||
}
|
||||
]
|
||||
})
|
||||
@@ -0,0 +1,23 @@
|
||||
<el-table
|
||||
:data="tableData"
|
||||
border
|
||||
style="width: 100%">
|
||||
<el-table-column
|
||||
prop="date"
|
||||
label="日期"
|
||||
width="180">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="抬头"
|
||||
width="180">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="address"
|
||||
label="餐饮商户">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="address"
|
||||
label="金额">
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -0,0 +1,531 @@
|
||||
<template>
|
||||
<div class="main">
|
||||
<div class="group">
|
||||
<!-- <el-form ref="form" :model="form" :rules="rules" label-width="80px"> -->
|
||||
<!-- <el-form ref="form" :model="form" label-width="800px"> -->
|
||||
<el-form ref="billForm" :model="bill" :rules="rules" label-width="80px">
|
||||
<el-form-item label="邮寄地址" prop="postContact">
|
||||
<!--邮寄地址-->
|
||||
<el-autocomplete
|
||||
class="posts"
|
||||
popper-class="my-autocomplete"
|
||||
v-model="bill.postContact"
|
||||
:fetch-suggestions="querySearchAsyncPosts"
|
||||
placeholder="请输选择邮寄地址"
|
||||
@select="handleSelectPosts" :disabled="disabled">
|
||||
<i class="el-icon-edit el-input__icon" slot="suffix" @click="handleIconClickPosts"></i>
|
||||
<template slot-scope="{ item }">
|
||||
<div class="name">{{ item.contact }}</div>
|
||||
<span class="subtitle">{{ item.address }}</span>
|
||||
<span class="subtitle">;</span>
|
||||
<span class="subtitle">{{ item.mobile }}</span>
|
||||
<span class="subtitle">;</span>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
|
||||
<div class="gTable">
|
||||
<!--增删改查-->
|
||||
<!--明细-->
|
||||
<!-- <el-form-item label="明细" prop="username"> -->
|
||||
<!--分割线-->
|
||||
<!-- <span><el-divider></el-divider></span> -->
|
||||
<el-table :data="bill.billItems" height="400px" style="width: 100%">
|
||||
<el-table-column prop="dating" label="日期" width="100" ></el-table-column>
|
||||
<el-table-column prop="titleAbbr" label="抬头" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-popover trigger="hover" placement="top">
|
||||
<p>税号: {{ scope.row.taxNo }}</p>
|
||||
<p>抬头: {{ scope.row.titleName }}</p>
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium">{{ scope.row.titleAbbr }}</el-tag>
|
||||
</div>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="merchantAbbr" label="餐饮商户" width="150" ></el-table-column>
|
||||
<el-table-column prop="amount" label="金额" width="80" ></el-table-column>
|
||||
<el-table-column align="right" >
|
||||
<template slot="header" slot-scope="scope">
|
||||
<!-- <el-button class="itemBtn" type="primary" size="medium" @click="clearFocusRow();isAddShow = true;resetForm('addForm');" :disabled="disabled">添加</el-button> -->
|
||||
<el-button class="itemBtn" type="primary" size="small" @click="clearFocusRow();isAddShow = true;resetForm('addForm');" :disabled="disabled">添加</el-button>
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<el-button-group>
|
||||
<!-- type="success" -->
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-edit"
|
||||
@click="handleEdit(scope.$index, scope.row)" :disabled="disabled">编辑</el-button>
|
||||
<!-- type="danger" -->
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-delete"
|
||||
@click.native.prevent="handleDelete(scope.$index,bill.billItems)" :disabled="disabled">删除</el-button>
|
||||
</el-button-group>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- </el-form-item> -->
|
||||
</div>
|
||||
<el-form-item label-width="2px">
|
||||
<el-button class="submit" type="primary" @click="onSubmit('billForm')" :disabled="disabled">提交</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!--增加-->
|
||||
<div width="600px">
|
||||
<el-dialog title="增加" :visible.sync="isAddShow" width="700px" >
|
||||
<el-form ref="addForm" :model="focusRow" :rules="rules" label-width="80px">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<!--抬头-->
|
||||
<el-form-item label="抬头简称" prop="titleAbbr">
|
||||
<el-autocomplete class="titles" popper-class="my-autocomplete" v-model="focusRow.titleAbbr" :fetch-suggestions="querySearchAsyncTitles" placeholder="请输选择抬头" @select="handleSelectTitles" >
|
||||
<i class="el-icon-edit el-input__icon" slot="suffix" @click="handleIconClickTitles" ></i>
|
||||
<template slot-scope="{ item }">
|
||||
<div class="name">{{ item.abbr }}</div>
|
||||
<span class="subtitle">{{ item.name }}</span>
|
||||
<span class="subtitle">{{ item.taxNo }}</span>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!--商户-->
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="开票商家" prop="merchantAbbr">
|
||||
<el-autocomplete class="merchants" v-model="focusRow.merchantAbbr" :fetch-suggestions="querySearchAsyncMerchant" placeholder="请选择餐饮商户" @select="handleSelectMerchant">
|
||||
<i class="el-icon-edit el-input__icon" slot="suffix" @click="handleIconClickTitles" ></i>
|
||||
<template slot-scope="{ item }">
|
||||
<div class="name">{{ item.abbr }}</div>
|
||||
<span class="subtitle">{{ item.name }}</span>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!--日期 & 金额-->
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<!--开票日期-->
|
||||
<el-form-item label="开票日期" prop="dating">
|
||||
<el-date-picker type="date" placeholder="选择日期" v-model="focusRow.dating" style="width: 100%;" value-format="yyyy-MM-dd"> </el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
<!--金额-->
|
||||
<el-form-item label="开票金额" prop="amount">
|
||||
<el-input-number v-model="focusRow.amount" :precision="2" :step="100" controls-position="right" :min="0" :max="5000"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="addItem('addForm')" :disabled="disabled">确 定</el-button>
|
||||
<el-button @click="resetForm('addForm')">重置</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<!--编辑-->
|
||||
<div width="600px">
|
||||
<el-dialog title="编辑" :visible.sync="isEditShow" width="700px" >
|
||||
<el-form ref="editForm" :model="focusRow" :rules="rules" label-width="80px">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<!--抬头-->
|
||||
<el-form-item label="抬头简称" prop="titleAbbr">
|
||||
<el-autocomplete class="titles" popper-class="my-autocomplete" v-model="focusRow.titleAbbr" :fetch-suggestions="querySearchAsyncTitles" placeholder="请输选择抬头" @select="handleSelectTitles" >
|
||||
<i class="el-icon-edit el-input__icon" slot="suffix" @click="handleIconClickTitles" ></i>
|
||||
<template slot-scope="{ item }">
|
||||
<div class="name">{{ item.abbr }}</div>
|
||||
<span class="subtitle">{{ item.name }}</span>
|
||||
<span class="subtitle">{{ item.taxNo }}</span>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!--商户-->
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="开票商家" prop="merchantAbbr">
|
||||
<el-autocomplete class="merchants" v-model="focusRow.merchantAbbr" :fetch-suggestions="querySearchAsyncMerchant" placeholder="请选择餐饮商户" @select="handleSelectMerchant">
|
||||
<i class="el-icon-edit el-input__icon" slot="suffix" @click="handleIconClickTitles" ></i>
|
||||
<template slot-scope="{ item }">
|
||||
<div class="name">{{ item.abbr }}</div>
|
||||
<span class="subtitle">{{ item.name }}</span>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!--日期 & 金额-->
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<!--开票日期-->
|
||||
<el-form-item label="开票日期" prop="dating">
|
||||
<el-date-picker type="date" placeholder="选择日期" v-model="focusRow.dating" style="width: 100%;" value-format="yyyy-MM-dd"> </el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
<!--金额-->
|
||||
<el-form-item label="开票金额" prop="amount">
|
||||
<el-input-number v-model="focusRow.amount" :precision="2" :step="100" controls-position="right" :min="0" :max="5000"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="updateItem('editForm')" :disabled="disabled">确 定</el-button>
|
||||
<!-- <el-button type="primary" @click="updateItem()" >确 定</el-button> -->
|
||||
<el-button @click="resetForm('editForm')">重置</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import { addPost, fetchPosts, getPost, fetchTitles, fetchMerchants, newBill } from "../api/basic.js";
|
||||
export default {
|
||||
name: "Bill",
|
||||
data() {
|
||||
return {
|
||||
isAddShow: false,
|
||||
isEditShow: false,
|
||||
posts: [],
|
||||
titles: [],
|
||||
merchants: [],
|
||||
addBtnDisabled: false,
|
||||
editBtnDisabled: false,
|
||||
disabled: false,
|
||||
// focusRow: { index: null,dating: "2019-05-28", titleId: null, titleAbbr: "上海沐融",titleName:"",taxNo:"",merchantId: null, merchantAbbr: "华容月",amount: 0.0 },
|
||||
focusRow: {},
|
||||
bill: {
|
||||
postId: "",
|
||||
// postAddress: "",
|
||||
postContact : "",
|
||||
// postMobile : "",
|
||||
postId: "",
|
||||
// postAddress: "",
|
||||
billItems: [
|
||||
// { dating: "2019-05-28", titleId: null, titleAbbr: "上海沐融",titleName:"",taxNo: "" ,merchantId: null, merchantAbbr: "华容月",amount: 0.0 },
|
||||
// { dating: "2019-05-28", titleId: null, titleAbbr: "上海沐融",titleName:"",taxNo: "" ,merchantId: null, merchantAbbr: "华容月",amount: 0.0 },
|
||||
// { dating: "2019-05-28", titleId: null, titleAbbr: "上海沐融",merchantId: null, merchantAbbr: "华容月",amount: 0.0 },
|
||||
// { dating: "2019-05-28", titleId: null, titleAbbr: "上海沐融",merchantId: null, merchantAbbr: "华容月",amount: 0.0 },
|
||||
// { dating: "2019-05-28", titleId: null, titleAbbr: "上海沐融",merchantId: null, merchantAbbr: "华容月",amount: 0.0 },
|
||||
],
|
||||
},
|
||||
rules: {
|
||||
postContact: [
|
||||
{ required: true, message: "请选择邮寄地址",trigger: "change"},
|
||||
// { min: 3, max: 15, message: "长度在 3 到 15 个字符", trigger: "blur" }
|
||||
],
|
||||
merchantAbbr: [
|
||||
{ required: true, message: "请选择餐饮商户", trigger: "change"},
|
||||
],
|
||||
titleAbbr: [
|
||||
{ required: true, message: "请选择抬头", trigger: "change" },
|
||||
],
|
||||
dating: [
|
||||
{ required: true, message: "选择日期", trigger: "blur" },
|
||||
],
|
||||
amount: [
|
||||
{ required: true, message: "请输入金额", trigger: "blur" },
|
||||
{ type: 'number', message: '金额必须为数字值'}
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
resetForm(formName) {
|
||||
this.$refs[formName].resetFields();
|
||||
// this.disabled = false;
|
||||
// this.clearFocusRow();
|
||||
},
|
||||
/** 在表格中添加明细 */
|
||||
addItem(formName) {
|
||||
var oriForm = formName;
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
console.info('addItem');
|
||||
console.info('focusRow:' + JSON.stringify(this.focusRow));
|
||||
console.info('this.bill.billItems:' + JSON.stringify(this.bill.billItems));
|
||||
this.bill.billItems.splice(0,0,this.focusRow);
|
||||
console.info('this.bill.billItems:' + JSON.stringify(this.bill.billItems));
|
||||
this.clearFocusRow();
|
||||
console.info('focusRow:' + JSON.stringify(this.focusRow));
|
||||
this.isAddShow = false;
|
||||
// this.resetForm(oriForm);
|
||||
} else {
|
||||
console.log('error submit!!');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 在表格中添加明细 */
|
||||
updateItem(formName) {
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
console.info('index:' + index);
|
||||
console.info('updateItem');
|
||||
console.info('focusRow:' + JSON.stringify(this.focusRow));
|
||||
console.info('this.bill.billItems:' + JSON.stringify(this.bill.billItems));
|
||||
var index = this.focusRow.index;
|
||||
this.bill.billItems.splice(index,1,this.focusRow);
|
||||
console.info('this.bill.billItems:' + JSON.stringify(this.bill.billItems));
|
||||
this.clearFocusRow();
|
||||
console.info('focusRow:' + JSON.stringify(this.focusRow));
|
||||
this.isEditShow = false;
|
||||
} else {
|
||||
console.log('error submit!!');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 表格-编辑一行 */
|
||||
handleEdit(index, row) {
|
||||
this.focusRow = row;
|
||||
this.focusRow.index = index;
|
||||
console.log(index, row);
|
||||
this.isEditShow = true;
|
||||
},
|
||||
handleDelete(index, row) {
|
||||
console.log(index, row);
|
||||
row.splice(index, 1);
|
||||
},
|
||||
onSubmit(formName) {
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
console.info("bill:" + JSON.stringify(this.bill));
|
||||
newBill(this.bill).then(function(response){
|
||||
console.info("response:" + response)
|
||||
})
|
||||
this.disabled = true;
|
||||
this.$message({ message: "提交成功", type: "success" });
|
||||
} else {
|
||||
console.log('error submit!!');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
reset(formName) {
|
||||
// this.$refs[formName].resetFields();
|
||||
// this.disabled = false;
|
||||
},
|
||||
// querySearch(queryString, cb) {
|
||||
// var posts = this.posts;
|
||||
// console.error("posts:" + posts);
|
||||
// var results = queryString ? posts.filter(this.createFilter(queryString)) : posts;
|
||||
// // 调用 callback 返回建议列表的数据
|
||||
// cb(results);
|
||||
// },
|
||||
/** AutoComplete Posts 处理*/
|
||||
querySearchAsyncPosts(queryString, cb) {
|
||||
var list = [{}];
|
||||
fetchPosts().then(function(response){
|
||||
for(let i of response.data){
|
||||
i.value = i.contact; //将想要展示的数据作为value
|
||||
// i.value = i.contact; //将想要展示的数据作为value
|
||||
}
|
||||
list = response.data;
|
||||
cb(list);
|
||||
})
|
||||
|
||||
// var posts = this.posts;
|
||||
// console.error("posts:" + posts);
|
||||
// var results = queryString ? posts.filter(this.createFilter(queryString)) : posts;
|
||||
// // 调用 callback 返回建议列表的数据
|
||||
// cb(results);
|
||||
},
|
||||
createFilterPosts(queryString) {
|
||||
return posts => {
|
||||
return (
|
||||
posts.contact.toLowerCase().indexOf(queryString.toLowerCase()) === 0
|
||||
);
|
||||
};
|
||||
},
|
||||
loadPosts() {
|
||||
console.error('loadPosts');
|
||||
},
|
||||
handleSelectPosts(item) {
|
||||
this.bill.postId = item.id;
|
||||
console.log('postId:' + this.bill.postId );
|
||||
console.log('postContact:' + this.bill.postContact );
|
||||
},
|
||||
handleIconClickPosts(ev) {
|
||||
console.log(ev);
|
||||
},
|
||||
|
||||
/** AutoComplete Titles 处理*/
|
||||
querySearchAsyncTitles(queryString, cb) {
|
||||
var list = [{}];
|
||||
fetchTitles().then(function(response){
|
||||
console.info(response)
|
||||
for(let i of response.data){
|
||||
i.value = i.abbr; // 将想要展示的数据作为value
|
||||
}
|
||||
list = response.data;
|
||||
cb(list);
|
||||
})
|
||||
},
|
||||
createFilterTitles(queryString) {
|
||||
return titles => {
|
||||
return (
|
||||
titles.abbr.toLowerCase().indexOf(queryString.toLowerCase()) === 0
|
||||
);
|
||||
};
|
||||
},
|
||||
loadTitles() {
|
||||
console.error('loadTitles');
|
||||
},
|
||||
handleSelectTitles(item) {
|
||||
this.focusRow.titleId = item.id;
|
||||
this.focusRow.titleName = item.name;
|
||||
this.focusRow.taxNo = item.taxNo;
|
||||
console.log('titleId:' + this.focusRow.titleId );
|
||||
console.log('titleAbbr:' + this.focusRow.titleAbbr );
|
||||
console.log('titleName:' + this.focusRow.titleName );
|
||||
},
|
||||
handleIconClickTitles(ev) {
|
||||
console.log(ev);
|
||||
},
|
||||
/** AutoComplete Merchant 处理*/
|
||||
querySearchAsyncMerchant(queryString, cb) {
|
||||
var list = [{}];
|
||||
fetchMerchants().then(function(response){
|
||||
for(let i of response.data){
|
||||
i.value = i.abbr; // 将想要展示的数据作为value
|
||||
}
|
||||
list = response.data;
|
||||
cb(list);
|
||||
})
|
||||
},
|
||||
createFilterMerchant(queryString) {
|
||||
return merchants => {
|
||||
return (
|
||||
merchants.contact.toLowerCase().indexOf(queryString.toLowerCase()) === 0
|
||||
);
|
||||
};
|
||||
},
|
||||
handleSelectMerchant(item) {
|
||||
this.focusRow.merchantId = item.id;
|
||||
this.focusRow.merchantsAbbr = item.abbr;
|
||||
console.log('merchantId:' + this.focusRow.merchantId );
|
||||
console.log('merchantsAbbr:' + this.focusRow.merchantsAbbr );
|
||||
console.log('merchantsName:' + item.name );
|
||||
},
|
||||
handleIconClickMerchant(ev) {
|
||||
console.log(ev);
|
||||
},
|
||||
loadMerchant() {
|
||||
console.error('loadTitles');
|
||||
},
|
||||
/** 清理当前缓存 */
|
||||
clearFocusRow() {
|
||||
this.focusRow = {}
|
||||
console.info('clearFocusRow');
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
// this.posts = this.loadPosts();
|
||||
// console.info('mounted.this.posts:' + posts);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
.subtitle{
|
||||
font-size: 12px;
|
||||
color: #b4b4b4;
|
||||
}
|
||||
h1,
|
||||
h2 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
|
||||
.el-form-item{
|
||||
/* width: 200px; */
|
||||
/* margin: 10px; */
|
||||
float:inherit ;
|
||||
padding: 20px;
|
||||
}
|
||||
.group {
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
/* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); */
|
||||
text-align: center;
|
||||
width: 800px;
|
||||
/* border-inline-width: 80px; */
|
||||
/* padding: 24px; */
|
||||
border-radius: 8px;
|
||||
align-self: center;
|
||||
text-align: left;
|
||||
margin: auto;
|
||||
/* position: absolute; */
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.gTable{
|
||||
/* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
|
||||
/* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); */
|
||||
text-align: left;
|
||||
width: 700px;
|
||||
/* border-inline-width: 80px; */
|
||||
/* padding: 24px; */
|
||||
/* border-radius: 8px; */
|
||||
align-self: left;
|
||||
margin-left: 24px;
|
||||
/* margin: auto; */
|
||||
/* position: absolute; */
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.itemBtn {
|
||||
width: 100px;
|
||||
float:right;
|
||||
}
|
||||
.el-form {
|
||||
/* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); */
|
||||
/* border-inline-width: 80px; */
|
||||
/* border-inline-width: 200px; */
|
||||
padding: 24px;
|
||||
border-radius: 4px;
|
||||
/* align-self: center; */
|
||||
align-self: center;
|
||||
text-align: left;
|
||||
/* width: 800px; */
|
||||
}
|
||||
.posts,.titles,.merchants{
|
||||
width: 487px;
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.submit {
|
||||
width: 100px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,531 @@
|
||||
<template>
|
||||
<div class="main">
|
||||
<div class="group">
|
||||
<!-- <el-form ref="form" :model="form" :rules="rules" label-width="80px"> -->
|
||||
<!-- <el-form ref="form" :model="form" label-width="800px"> -->
|
||||
<el-form ref="billForm" :model="bill" :rules="rules" label-width="80px">
|
||||
<el-form-item label="邮寄地址" prop="postContact">
|
||||
<!--邮寄地址-->
|
||||
<el-autocomplete
|
||||
class="posts"
|
||||
popper-class="my-autocomplete"
|
||||
v-model="bill.postContact"
|
||||
:fetch-suggestions="querySearchAsyncPosts"
|
||||
placeholder="请输选择邮寄地址"
|
||||
@select="handleSelectPosts" :disabled="disabled">
|
||||
<i class="el-icon-edit el-input__icon" slot="suffix" @click="handleIconClickPosts"></i>
|
||||
<template slot-scope="{ item }">
|
||||
<div class="name">{{ item.contact }}</div>
|
||||
<span class="subtitle">{{ item.address }}</span>
|
||||
<span class="subtitle">;</span>
|
||||
<span class="subtitle">{{ item.mobile }}</span>
|
||||
<span class="subtitle">;</span>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
|
||||
<div class="gTable">
|
||||
<!--增删改查-->
|
||||
<!--明细-->
|
||||
<!-- <el-form-item label="明细" prop="username"> -->
|
||||
<!--分割线-->
|
||||
<!-- <span><el-divider></el-divider></span> -->
|
||||
<el-table :data="bill.billItems" height="400px" style="width: 100%">
|
||||
<el-table-column prop="dating" label="日期" width="100" ></el-table-column>
|
||||
<el-table-column prop="titleAbbr" label="抬头" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-popover trigger="hover" placement="top">
|
||||
<p>税号: {{ scope.row.taxNo }}</p>
|
||||
<p>抬头: {{ scope.row.titleName }}</p>
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-tag size="medium">{{ scope.row.titleAbbr }}</el-tag>
|
||||
</div>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="merchantAbbr" label="餐饮商户" width="150" ></el-table-column>
|
||||
<el-table-column prop="amount" label="金额" width="80" ></el-table-column>
|
||||
<el-table-column align="right" >
|
||||
<template slot="header" slot-scope="scope">
|
||||
<!-- <el-button class="itemBtn" type="primary" size="medium" @click="clearFocusRow();isAddShow = true;resetForm('addForm');" :disabled="disabled">添加</el-button> -->
|
||||
<el-button class="itemBtn" type="primary" size="small" @click="clearFocusRow();isAddShow = true;resetForm('addForm');" :disabled="disabled">添加</el-button>
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<el-button-group>
|
||||
<!-- type="success" -->
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-edit"
|
||||
@click="handleEdit(scope.$index, scope.row)" :disabled="disabled">编辑</el-button>
|
||||
<!-- type="danger" -->
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-delete"
|
||||
@click.native.prevent="handleDelete(scope.$index,bill.billItems)" :disabled="disabled">删除</el-button>
|
||||
</el-button-group>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- </el-form-item> -->
|
||||
</div>
|
||||
<el-form-item label-width="2px">
|
||||
<el-button class="submit" type="primary" @click="onSubmit('billForm')" :disabled="disabled">提交</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!--增加-->
|
||||
<div width="600px">
|
||||
<el-dialog title="增加" :visible.sync="isAddShow" width="700px" >
|
||||
<el-form ref="addForm" :model="focusRow" :rules="rules" label-width="80px">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<!--抬头-->
|
||||
<el-form-item label="抬头简称" prop="titleAbbr">
|
||||
<el-autocomplete class="titles" popper-class="my-autocomplete" v-model="focusRow.titleAbbr" :fetch-suggestions="querySearchAsyncTitles" placeholder="请输选择抬头" @select="handleSelectTitles" >
|
||||
<i class="el-icon-edit el-input__icon" slot="suffix" @click="handleIconClickTitles" ></i>
|
||||
<template slot-scope="{ item }">
|
||||
<div class="name">{{ item.abbr }}</div>
|
||||
<span class="subtitle">{{ item.name }}</span>
|
||||
<span class="subtitle">{{ item.taxNo }}</span>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!--商户-->
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="开票商家" prop="merchantAbbr">
|
||||
<el-autocomplete class="merchants" v-model="focusRow.merchantAbbr" :fetch-suggestions="querySearchAsyncMerchant" placeholder="请选择餐饮商户" @select="handleSelectMerchant">
|
||||
<i class="el-icon-edit el-input__icon" slot="suffix" @click="handleIconClickTitles" ></i>
|
||||
<template slot-scope="{ item }">
|
||||
<div class="name">{{ item.abbr }}</div>
|
||||
<span class="subtitle">{{ item.name }}</span>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!--日期 & 金额-->
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<!--开票日期-->
|
||||
<el-form-item label="开票日期" prop="dating">
|
||||
<el-date-picker type="date" placeholder="选择日期" v-model="focusRow.dating" style="width: 100%;" value-format="yyyy-MM-dd"> </el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
<!--金额-->
|
||||
<el-form-item label="开票金额" prop="amount">
|
||||
<el-input-number v-model="focusRow.amount" :precision="2" :step="100" controls-position="right" :min="0" :max="5000"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="addItem('addForm')" :disabled="disabled">确 定</el-button>
|
||||
<el-button @click="resetForm('addForm')">重置</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<!--编辑-->
|
||||
<div width="600px">
|
||||
<el-dialog title="编辑" :visible.sync="isEditShow" width="700px" >
|
||||
<el-form ref="editForm" :model="focusRow" :rules="rules" label-width="80px">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<!--抬头-->
|
||||
<el-form-item label="抬头简称" prop="titleAbbr">
|
||||
<el-autocomplete class="titles" popper-class="my-autocomplete" v-model="focusRow.titleAbbr" :fetch-suggestions="querySearchAsyncTitles" placeholder="请输选择抬头" @select="handleSelectTitles" >
|
||||
<i class="el-icon-edit el-input__icon" slot="suffix" @click="handleIconClickTitles" ></i>
|
||||
<template slot-scope="{ item }">
|
||||
<div class="name">{{ item.abbr }}</div>
|
||||
<span class="subtitle">{{ item.name }}</span>
|
||||
<span class="subtitle">{{ item.taxNo }}</span>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!--商户-->
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="开票商家" prop="merchantAbbr">
|
||||
<el-autocomplete class="merchants" v-model="focusRow.merchantAbbr" :fetch-suggestions="querySearchAsyncMerchant" placeholder="请选择餐饮商户" @select="handleSelectMerchant">
|
||||
<i class="el-icon-edit el-input__icon" slot="suffix" @click="handleIconClickTitles" ></i>
|
||||
<template slot-scope="{ item }">
|
||||
<div class="name">{{ item.abbr }}</div>
|
||||
<span class="subtitle">{{ item.name }}</span>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!--日期 & 金额-->
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<!--开票日期-->
|
||||
<el-form-item label="开票日期" prop="dating">
|
||||
<el-date-picker type="date" placeholder="选择日期" v-model="focusRow.dating" style="width: 100%;" value-format="yyyy-MM-dd"> </el-date-picker>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="1">
|
||||
<!--金额-->
|
||||
<el-form-item label="开票金额" prop="amount">
|
||||
<el-input-number v-model="focusRow.amount" :precision="2" :step="100" controls-position="right" :min="0" :max="5000"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="updateItem('editForm')" :disabled="disabled">确 定</el-button>
|
||||
<!-- <el-button type="primary" @click="updateItem()" >确 定</el-button> -->
|
||||
<el-button @click="resetForm('editForm')">重置</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import { addPost, fetchPosts, getPost, fetchTitles, fetchMerchants, newBill } from "../api/basic.js";
|
||||
export default {
|
||||
name: "Bill",
|
||||
data() {
|
||||
return {
|
||||
isAddShow: false,
|
||||
isEditShow: false,
|
||||
posts: [],
|
||||
titles: [],
|
||||
merchants: [],
|
||||
addBtnDisabled: false,
|
||||
editBtnDisabled: false,
|
||||
disabled: false,
|
||||
// focusRow: { index: null,dating: "2019-05-28", titleId: null, titleAbbr: "上海沐融",titleName:"",taxNo:"",merchantId: null, merchantAbbr: "华容月",amount: 0.0 },
|
||||
focusRow: {},
|
||||
bill: {
|
||||
postId: "",
|
||||
// postAddress: "",
|
||||
postContact : "",
|
||||
// postMobile : "",
|
||||
postId: "",
|
||||
// postAddress: "",
|
||||
billItems: [
|
||||
// { dating: "2019-05-28", titleId: null, titleAbbr: "上海沐融",titleName:"",taxNo: "" ,merchantId: null, merchantAbbr: "华容月",amount: 0.0 },
|
||||
// { dating: "2019-05-28", titleId: null, titleAbbr: "上海沐融",titleName:"",taxNo: "" ,merchantId: null, merchantAbbr: "华容月",amount: 0.0 },
|
||||
// { dating: "2019-05-28", titleId: null, titleAbbr: "上海沐融",merchantId: null, merchantAbbr: "华容月",amount: 0.0 },
|
||||
// { dating: "2019-05-28", titleId: null, titleAbbr: "上海沐融",merchantId: null, merchantAbbr: "华容月",amount: 0.0 },
|
||||
// { dating: "2019-05-28", titleId: null, titleAbbr: "上海沐融",merchantId: null, merchantAbbr: "华容月",amount: 0.0 },
|
||||
],
|
||||
},
|
||||
rules: {
|
||||
postContact: [
|
||||
{ required: true, message: "请选择邮寄地址",trigger: "change"},
|
||||
// { min: 3, max: 15, message: "长度在 3 到 15 个字符", trigger: "blur" }
|
||||
],
|
||||
merchantAbbr: [
|
||||
{ required: true, message: "请选择餐饮商户", trigger: "change"},
|
||||
],
|
||||
titleAbbr: [
|
||||
{ required: true, message: "请选择抬头", trigger: "change" },
|
||||
],
|
||||
dating: [
|
||||
{ required: true, message: "选择日期", trigger: "blur" },
|
||||
],
|
||||
amount: [
|
||||
{ required: true, message: "请输入金额", trigger: "blur" },
|
||||
{ type: 'number', message: '金额必须为数字值'}
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
resetForm(formName) {
|
||||
this.$refs[formName].resetFields();
|
||||
// this.disabled = false;
|
||||
// this.clearFocusRow();
|
||||
},
|
||||
/** 在表格中添加明细 */
|
||||
addItem(formName) {
|
||||
var oriForm = formName;
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
console.info('addItem');
|
||||
console.info('focusRow:' + JSON.stringify(this.focusRow));
|
||||
console.info('this.bill.billItems:' + JSON.stringify(this.bill.billItems));
|
||||
this.bill.billItems.splice(0,0,this.focusRow);
|
||||
console.info('this.bill.billItems:' + JSON.stringify(this.bill.billItems));
|
||||
this.clearFocusRow();
|
||||
console.info('focusRow:' + JSON.stringify(this.focusRow));
|
||||
this.isAddShow = false;
|
||||
// this.resetForm(oriForm);
|
||||
} else {
|
||||
console.log('error submit!!');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 在表格中添加明细 */
|
||||
updateItem(formName) {
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
console.info('index:' + index);
|
||||
console.info('updateItem');
|
||||
console.info('focusRow:' + JSON.stringify(this.focusRow));
|
||||
console.info('this.bill.billItems:' + JSON.stringify(this.bill.billItems));
|
||||
var index = this.focusRow.index;
|
||||
this.bill.billItems.splice(index,1,this.focusRow);
|
||||
console.info('this.bill.billItems:' + JSON.stringify(this.bill.billItems));
|
||||
this.clearFocusRow();
|
||||
console.info('focusRow:' + JSON.stringify(this.focusRow));
|
||||
this.isEditShow = false;
|
||||
} else {
|
||||
console.log('error submit!!');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
/** 表格-编辑一行 */
|
||||
handleEdit(index, row) {
|
||||
this.focusRow = row;
|
||||
this.focusRow.index = index;
|
||||
console.log(index, row);
|
||||
this.isEditShow = true;
|
||||
},
|
||||
handleDelete(index, row) {
|
||||
console.log(index, row);
|
||||
row.splice(index, 1);
|
||||
},
|
||||
onSubmit(formName) {
|
||||
this.$refs[formName].validate((valid) => {
|
||||
if (valid) {
|
||||
console.info("bill:" + JSON.stringify(this.bill));
|
||||
newBill(this.bill).then(function(response){
|
||||
console.info("response:" + response)
|
||||
})
|
||||
this.disabled = true;
|
||||
this.$message({ message: "提交成功", type: "success" });
|
||||
} else {
|
||||
console.log('error submit!!');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
reset(formName) {
|
||||
// this.$refs[formName].resetFields();
|
||||
// this.disabled = false;
|
||||
},
|
||||
// querySearch(queryString, cb) {
|
||||
// var posts = this.posts;
|
||||
// console.error("posts:" + posts);
|
||||
// var results = queryString ? posts.filter(this.createFilter(queryString)) : posts;
|
||||
// // 调用 callback 返回建议列表的数据
|
||||
// cb(results);
|
||||
// },
|
||||
/** AutoComplete Posts 处理*/
|
||||
querySearchAsyncPosts(queryString, cb) {
|
||||
var list = [{}];
|
||||
fetchPosts().then(function(response){
|
||||
for(let i of response.data){
|
||||
i.value = i.contact; //将想要展示的数据作为value
|
||||
// i.value = i.contact; //将想要展示的数据作为value
|
||||
}
|
||||
list = response.data;
|
||||
cb(list);
|
||||
})
|
||||
|
||||
// var posts = this.posts;
|
||||
// console.error("posts:" + posts);
|
||||
// var results = queryString ? posts.filter(this.createFilter(queryString)) : posts;
|
||||
// // 调用 callback 返回建议列表的数据
|
||||
// cb(results);
|
||||
},
|
||||
createFilterPosts(queryString) {
|
||||
return posts => {
|
||||
return (
|
||||
posts.contact.toLowerCase().indexOf(queryString.toLowerCase()) === 0
|
||||
);
|
||||
};
|
||||
},
|
||||
loadPosts() {
|
||||
console.error('loadPosts');
|
||||
},
|
||||
handleSelectPosts(item) {
|
||||
this.bill.postId = item.id;
|
||||
console.log('postId:' + this.bill.postId );
|
||||
console.log('postContact:' + this.bill.postContact );
|
||||
},
|
||||
handleIconClickPosts(ev) {
|
||||
console.log(ev);
|
||||
},
|
||||
|
||||
/** AutoComplete Titles 处理*/
|
||||
querySearchAsyncTitles(queryString, cb) {
|
||||
var list = [{}];
|
||||
fetchTitles().then(function(response){
|
||||
console.info(response)
|
||||
for(let i of response.data){
|
||||
i.value = i.abbr; // 将想要展示的数据作为value
|
||||
}
|
||||
list = response.data;
|
||||
cb(list);
|
||||
})
|
||||
},
|
||||
createFilterTitles(queryString) {
|
||||
return titles => {
|
||||
return (
|
||||
titles.abbr.toLowerCase().indexOf(queryString.toLowerCase()) === 0
|
||||
);
|
||||
};
|
||||
},
|
||||
loadTitles() {
|
||||
console.error('loadTitles');
|
||||
},
|
||||
handleSelectTitles(item) {
|
||||
this.focusRow.titleId = item.id;
|
||||
this.focusRow.titleName = item.name;
|
||||
this.focusRow.taxNo = item.taxNo;
|
||||
console.log('titleId:' + this.focusRow.titleId );
|
||||
console.log('titleAbbr:' + this.focusRow.titleAbbr );
|
||||
console.log('titleName:' + this.focusRow.titleName );
|
||||
},
|
||||
handleIconClickTitles(ev) {
|
||||
console.log(ev);
|
||||
},
|
||||
/** AutoComplete Merchant 处理*/
|
||||
querySearchAsyncMerchant(queryString, cb) {
|
||||
var list = [{}];
|
||||
fetchMerchants().then(function(response){
|
||||
for(let i of response.data){
|
||||
i.value = i.abbr; // 将想要展示的数据作为value
|
||||
}
|
||||
list = response.data;
|
||||
cb(list);
|
||||
})
|
||||
},
|
||||
createFilterMerchant(queryString) {
|
||||
return merchants => {
|
||||
return (
|
||||
merchants.contact.toLowerCase().indexOf(queryString.toLowerCase()) === 0
|
||||
);
|
||||
};
|
||||
},
|
||||
handleSelectMerchant(item) {
|
||||
this.focusRow.merchantId = item.id;
|
||||
this.focusRow.merchantsAbbr = item.abbr;
|
||||
console.log('merchantId:' + this.focusRow.merchantId );
|
||||
console.log('merchantsAbbr:' + this.focusRow.merchantsAbbr );
|
||||
console.log('merchantsName:' + item.name );
|
||||
},
|
||||
handleIconClickMerchant(ev) {
|
||||
console.log(ev);
|
||||
},
|
||||
loadMerchant() {
|
||||
console.error('loadTitles');
|
||||
},
|
||||
/** 清理当前缓存 */
|
||||
clearFocusRow() {
|
||||
this.focusRow = {}
|
||||
console.info('clearFocusRow');
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
// this.posts = this.loadPosts();
|
||||
// console.info('mounted.this.posts:' + posts);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
.subtitle{
|
||||
font-size: 12px;
|
||||
color: #b4b4b4;
|
||||
}
|
||||
h1,
|
||||
h2 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
|
||||
.el-form-item{
|
||||
/* width: 200px; */
|
||||
/* margin: 10px; */
|
||||
float:inherit ;
|
||||
padding: 20px;
|
||||
}
|
||||
.group {
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
/* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); */
|
||||
text-align: center;
|
||||
width: 800px;
|
||||
/* border-inline-width: 80px; */
|
||||
/* padding: 24px; */
|
||||
border-radius: 8px;
|
||||
align-self: center;
|
||||
text-align: left;
|
||||
margin: auto;
|
||||
/* position: absolute; */
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.gTable{
|
||||
/* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
|
||||
/* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); */
|
||||
text-align: left;
|
||||
width: 700px;
|
||||
/* border-inline-width: 80px; */
|
||||
/* padding: 24px; */
|
||||
/* border-radius: 8px; */
|
||||
align-self: left;
|
||||
margin-left: 24px;
|
||||
/* margin: auto; */
|
||||
/* position: absolute; */
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.itemBtn {
|
||||
width: 100px;
|
||||
float:right;
|
||||
}
|
||||
.el-form {
|
||||
/* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); */
|
||||
/* border-inline-width: 80px; */
|
||||
/* border-inline-width: 200px; */
|
||||
padding: 24px;
|
||||
border-radius: 4px;
|
||||
/* align-self: center; */
|
||||
align-self: center;
|
||||
text-align: left;
|
||||
/* width: 800px; */
|
||||
}
|
||||
.posts,.titles,.merchants{
|
||||
width: 487px;
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.submit {
|
||||
width: 100px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,164 @@
|
||||
<template>
|
||||
<div class="login">
|
||||
<div class="group">
|
||||
<el-form ref="ruleForm" :model="ruleForm" :rules="rules" label-width="80px">
|
||||
<el-form-item label="用户名" prop="username">
|
||||
<el-input v-model="ruleForm.username" clearable placeholder="请输入用户名"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="密码" prop="password">
|
||||
<el-input v-model="ruleForm.password" @keyup.enter.native="onSubmit('ruleForm')" show-password placeholder="请输入密码"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit('ruleForm')" :disabled="disabled">登录</el-button>
|
||||
<el-button @click="reset('ruleForm')">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { UserLoginAction } from "../api/user.js";
|
||||
export default {
|
||||
name: "Login",
|
||||
data() {
|
||||
return {
|
||||
disabled: false,
|
||||
ruleForm: {
|
||||
username: "",
|
||||
password: ""
|
||||
},
|
||||
rules: {
|
||||
username: [
|
||||
{ required: true, message: "请输入户名", trigger: "blur" },
|
||||
{ min: 3, max: 15, message: "长度在 3 到 15 个字符", trigger: "blur" }
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: "请输入密码", trigger: "change" },
|
||||
{ min: 3, max: 15, message: "长度在 3 到 15 个字符", trigger: "blur" }
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onSubmit(formName) {
|
||||
this.$refs[formName].validate(valid => {
|
||||
var _this = this;
|
||||
if (valid) {
|
||||
UserLoginAction(this.ruleForm)
|
||||
.then(res => {
|
||||
var token = "Bearer " + res.data.token;
|
||||
console.log("token:" + token);
|
||||
window.localStorage.setItem("token", token);
|
||||
this.disabled = true;
|
||||
this.$message({ message: "登录成功", type: "success" });
|
||||
})
|
||||
.catch(function(error) {
|
||||
// _this.$message({ message: error.response.statusText, type: 'error' });
|
||||
// _this.$message.error();
|
||||
if (error.response) {
|
||||
// The request was made and the server responded with a status code
|
||||
// that falls out of the range of 2xx
|
||||
_this.$message({ message: error.response.data.message, type: 'error' });
|
||||
console.log(error.response.data);
|
||||
console.log(error.response.status);
|
||||
console.log(error.response.headers);
|
||||
} else if (error.request) {
|
||||
// The request was made but no response was received
|
||||
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
||||
// http.ClientRequest in node.js
|
||||
// _this.$message.error(error.request);
|
||||
console.log(error.request);
|
||||
_this.$message.error('未知错误');
|
||||
} else {
|
||||
// Something happened in setting up the request that triggered an Error
|
||||
console.log("Error", error.message);
|
||||
_this.$message.error(error.response.message);
|
||||
}
|
||||
console.log(error.config);
|
||||
// _this.$message.error(error.response.statusText);
|
||||
});
|
||||
} else {
|
||||
console.log("error submit!!");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
reset(formName) {
|
||||
this.$refs[formName].resetFields();
|
||||
this.disabled = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h1,
|
||||
h2 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
.group {
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
/* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); */
|
||||
text-align: center;
|
||||
width: 500px;
|
||||
/* border-inline-width: 80px; */
|
||||
/* padding: 24px; */
|
||||
border-radius: 8px;
|
||||
align-self: center;
|
||||
text-align: left;
|
||||
margin: auto;
|
||||
/* position: absolute; */
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.el-checkbox-group {
|
||||
width: 320px;
|
||||
float: left;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.el-checkbox {
|
||||
float: left;
|
||||
width: 160px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.el-radio-group {
|
||||
width: 320px;
|
||||
/* float:left; */
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.el-radio {
|
||||
float: left;
|
||||
width: 160px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.el-form {
|
||||
/* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); */
|
||||
border-inline-width: 80px;
|
||||
padding: 24px;
|
||||
border-radius: 4px;
|
||||
align-self: center;
|
||||
text-align: left;
|
||||
width: 350px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<div class="merchant">
|
||||
<div class="group">
|
||||
<!-- <form class="el-form bill"> -->
|
||||
<el-form ref="form" :model="form" label-width="80px">
|
||||
<el-form-item label="商户简称">
|
||||
<el-input v-model="merc.abbr"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="商户全称">
|
||||
<el-input v-model="merc.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit">立即创建</el-button>
|
||||
<el-button>取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- </form> -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { addMerchant, fetchMerchants, getMerchant } from "../api/basic.js";
|
||||
export default {
|
||||
name: "Merchant",
|
||||
data() {
|
||||
return {
|
||||
merc: {
|
||||
name: "",
|
||||
abbr: ""
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onSubmit() {
|
||||
console.log("submit!");
|
||||
console.log("merc:" + this.merc.name);
|
||||
// MerchantAddAction(JSON.stringify(this.merc))
|
||||
addMerchant(this.merc).then(res => {
|
||||
var merchantId = res.data.id;
|
||||
console.log("res.data.code" + res.data.code);
|
||||
this.$message({ message: "恭喜你,这是一条成功消息", type: "success" });
|
||||
getMerchant(merchantId);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h1,
|
||||
h2 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
.group {
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
/* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); */
|
||||
text-align: center;
|
||||
width: 600px;
|
||||
/* border-inline-width: 80px; */
|
||||
/* padding: 24px; */
|
||||
border-radius: 8px;
|
||||
align-self: center;
|
||||
text-align: left;
|
||||
margin: auto;
|
||||
/* position: absolute; */
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.merchant {
|
||||
/* margin: 0 auto; */
|
||||
/* text-align: center; */
|
||||
/* background-color: #fff; */
|
||||
/* border-radius: 20px; */
|
||||
/* width: 300px;
|
||||
height: 350px; */
|
||||
/* margin: auto; */
|
||||
/* position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0; */
|
||||
}
|
||||
.el-checkbox-group {
|
||||
width: 320px;
|
||||
float: left;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.el-checkbox {
|
||||
float: left;
|
||||
width: 160px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.el-radio-group {
|
||||
width: 320px;
|
||||
/* float:left; */
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.el-radio {
|
||||
float: left;
|
||||
width: 160px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.el-form {
|
||||
/* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); */
|
||||
border-inline-width: 80px;
|
||||
padding: 24px;
|
||||
border-radius: 4px;
|
||||
align-self: center;
|
||||
text-align: left;
|
||||
width: 480px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,168 @@
|
||||
<template>
|
||||
<div class="merchant">
|
||||
<div class="group">
|
||||
<form class="el-form bill">
|
||||
<el-form ref="form" :model="form" label-width="80px">
|
||||
<el-form-item label="活动名称">
|
||||
<el-input v-model="form.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动区域">
|
||||
<el-select v-model="form.region" placeholder="请选择活动区域">
|
||||
<el-option label="区域一" value="shanghai"></el-option>
|
||||
<el-option label="区域二" value="beijing"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动时间">
|
||||
<el-col :span="11">
|
||||
<el-date-picker
|
||||
type="date"
|
||||
placeholder="选择日期"
|
||||
v-model="form.date1"
|
||||
style="width: 100%;"
|
||||
></el-date-picker>
|
||||
</el-col>
|
||||
<el-col class="line" :span="2">-</el-col>
|
||||
<el-col :span="11">
|
||||
<el-time-picker placeholder="选择时间" v-model="form.date2" style="width: 100%;"></el-time-picker>
|
||||
</el-col>
|
||||
</el-form-item>
|
||||
<el-form-item label="即时配送">
|
||||
<el-switch v-model="form.delivery"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动性质">
|
||||
<el-checkbox-group v-model="form.type">
|
||||
<el-checkbox label="美食/餐厅线上活动" name="type"></el-checkbox>
|
||||
<el-checkbox label="地推活动" name="type"></el-checkbox>
|
||||
<el-checkbox label="线下主题活动" name="type"></el-checkbox>
|
||||
<el-checkbox label="单纯品牌曝光" name="type"></el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="特殊资源">
|
||||
<el-radio-group v-model="form.resource">
|
||||
<el-radio label="线上品牌商赞助"></el-radio>
|
||||
<el-radio label="线下场地免费"></el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="活动形式">
|
||||
<el-input type="textarea" v-model="form.desc"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="onSubmit">立即创建</el-button>
|
||||
<el-button>取消</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Merchant",
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
name: "",
|
||||
region: "",
|
||||
date1: "",
|
||||
date2: "",
|
||||
delivery: false,
|
||||
type: [],
|
||||
resource: "",
|
||||
desc: ""
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onSubmit() {
|
||||
console.log("submit!");
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h1,
|
||||
h2 {
|
||||
font-weight: normal;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
.group {
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
/* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); */
|
||||
text-align: center;
|
||||
width: 600px;
|
||||
/* border-inline-width: 80px; */
|
||||
/* padding: 24px; */
|
||||
border-radius: 8px;
|
||||
align-self: center;
|
||||
text-align: left;
|
||||
margin: auto;
|
||||
/* position: absolute; */
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.merchant {
|
||||
/* margin: 0 auto; */
|
||||
/* text-align: center; */
|
||||
/* background-color: #fff; */
|
||||
/* border-radius: 20px; */
|
||||
/* width: 300px;
|
||||
height: 350px; */
|
||||
/* margin: auto; */
|
||||
/* position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0; */
|
||||
}
|
||||
.el-checkbox-group {
|
||||
width: 320px;
|
||||
float:left;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.el-checkbox{
|
||||
float: left;
|
||||
width: 160px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.el-radio-group {
|
||||
width: 320px;
|
||||
/* float:left; */
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
.el-radio{
|
||||
float: left;
|
||||
width: 160px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.el-form {
|
||||
/* box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); */
|
||||
border-inline-width: 80px;
|
||||
padding: 24px;
|
||||
border-radius: 4px;
|
||||
align-self: center;
|
||||
text-align: left;
|
||||
width: 480px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,27 @@
|
||||
// A custom Nightwatch assertion.
|
||||
// The assertion name is the filename.
|
||||
// Example usage:
|
||||
//
|
||||
// browser.assert.elementCount(selector, count)
|
||||
//
|
||||
// For more information on custom assertions see:
|
||||
// http://nightwatchjs.org/guide#writing-custom-assertions
|
||||
|
||||
exports.assertion = function (selector, count) {
|
||||
this.message = 'Testing if element <' + selector + '> has count: ' + count
|
||||
this.expected = count
|
||||
this.pass = function (val) {
|
||||
return val === this.expected
|
||||
}
|
||||
this.value = function (res) {
|
||||
return res.value
|
||||
}
|
||||
this.command = function (cb) {
|
||||
var self = this
|
||||
return this.api.execute(function (selector) {
|
||||
return document.querySelectorAll(selector).length
|
||||
}, [selector], function (res) {
|
||||
cb.call(self, res)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
require('babel-register')
|
||||
var config = require('../../config')
|
||||
|
||||
// http://nightwatchjs.org/gettingstarted#settings-file
|
||||
module.exports = {
|
||||
src_folders: ['test/e2e/specs'],
|
||||
output_folder: 'test/e2e/reports',
|
||||
custom_assertions_path: ['test/e2e/custom-assertions'],
|
||||
|
||||
selenium: {
|
||||
start_process: true,
|
||||
server_path: require('selenium-server').path,
|
||||
host: '127.0.0.1',
|
||||
port: 4444,
|
||||
cli_args: {
|
||||
'webdriver.chrome.driver': require('chromedriver').path
|
||||
}
|
||||
},
|
||||
|
||||
test_settings: {
|
||||
default: {
|
||||
selenium_port: 4444,
|
||||
selenium_host: 'localhost',
|
||||
silent: true,
|
||||
globals: {
|
||||
devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
|
||||
}
|
||||
},
|
||||
|
||||
chrome: {
|
||||
desiredCapabilities: {
|
||||
browserName: 'chrome',
|
||||
javascriptEnabled: true,
|
||||
acceptSslCerts: true
|
||||
}
|
||||
},
|
||||
|
||||
firefox: {
|
||||
desiredCapabilities: {
|
||||
browserName: 'firefox',
|
||||
javascriptEnabled: true,
|
||||
acceptSslCerts: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// 1. start the dev server using production config
|
||||
process.env.NODE_ENV = 'testing'
|
||||
|
||||
const webpack = require('webpack')
|
||||
const DevServer = require('webpack-dev-server')
|
||||
|
||||
const webpackConfig = require('../../build/webpack.prod.conf')
|
||||
const devConfigPromise = require('../../build/webpack.dev.conf')
|
||||
|
||||
let server
|
||||
|
||||
devConfigPromise.then(devConfig => {
|
||||
const devServerOptions = devConfig.devServer
|
||||
const compiler = webpack(webpackConfig)
|
||||
server = new DevServer(compiler, devServerOptions)
|
||||
const port = devServerOptions.port
|
||||
const host = devServerOptions.host
|
||||
return server.listen(port, host)
|
||||
})
|
||||
.then(() => {
|
||||
// 2. run the nightwatch test suite against it
|
||||
// to run in additional browsers:
|
||||
// 1. add an entry in test/e2e/nightwatch.conf.js under "test_settings"
|
||||
// 2. add it to the --env flag below
|
||||
// or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
|
||||
// For more information on Nightwatch's config file, see
|
||||
// http://nightwatchjs.org/guide#settings-file
|
||||
let opts = process.argv.slice(2)
|
||||
if (opts.indexOf('--config') === -1) {
|
||||
opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js'])
|
||||
}
|
||||
if (opts.indexOf('--env') === -1) {
|
||||
opts = opts.concat(['--env', 'chrome'])
|
||||
}
|
||||
|
||||
const spawn = require('cross-spawn')
|
||||
const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
|
||||
|
||||
runner.on('exit', function (code) {
|
||||
server.close()
|
||||
process.exit(code)
|
||||
})
|
||||
|
||||
runner.on('error', function (err) {
|
||||
server.close()
|
||||
throw err
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,19 @@
|
||||
// For authoring Nightwatch tests, see
|
||||
// http://nightwatchjs.org/guide#usage
|
||||
|
||||
module.exports = {
|
||||
'default e2e tests': function (browser) {
|
||||
// automatically uses dev Server port from /config.index.js
|
||||
// default: http://localhost:8080
|
||||
// see nightwatch.conf.js
|
||||
const devServer = browser.globals.devServerURL
|
||||
|
||||
browser
|
||||
.url(devServer)
|
||||
.waitForElementVisible('#app', 5000)
|
||||
.assert.elementPresent('.hello')
|
||||
.assert.containsText('h1', 'Welcome to Your Vue.js App')
|
||||
.assert.elementCount('img', 1)
|
||||
.end()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"env": {
|
||||
"jest": true
|
||||
},
|
||||
"globals": {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
rootDir: path.resolve(__dirname, '../../'),
|
||||
moduleFileExtensions: [
|
||||
'js',
|
||||
'json',
|
||||
'vue'
|
||||
],
|
||||
moduleNameMapper: {
|
||||
'^@/(.*)$': '<rootDir>/src/$1'
|
||||
},
|
||||
transform: {
|
||||
'^.+\\.js$': '<rootDir>/node_modules/babel-jest',
|
||||
'.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
|
||||
},
|
||||
testPathIgnorePatterns: [
|
||||
'<rootDir>/test/e2e'
|
||||
],
|
||||
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
|
||||
setupFiles: ['<rootDir>/test/unit/setup'],
|
||||
mapCoverage: true,
|
||||
coverageDirectory: '<rootDir>/test/unit/coverage',
|
||||
collectCoverageFrom: [
|
||||
'src/**/*.{js,vue}',
|
||||
'!src/main.js',
|
||||
'!src/router/index.js',
|
||||
'!**/node_modules/**'
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
@@ -0,0 +1,11 @@
|
||||
import Vue from 'vue'
|
||||
import HelloWorld from '@/components/HelloWorld'
|
||||
|
||||
describe('HelloWorld.vue', () => {
|
||||
it('should render correct contents', () => {
|
||||
const Constructor = Vue.extend(HelloWorld)
|
||||
const vm = new Constructor().$mount()
|
||||
expect(vm.$el.querySelector('.hello h1').textContent)
|
||||
.toEqual('Welcome to Your Vue.js App')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user