diff --git a/.env.development b/.env.development
index de583d0940..51ce4c83f3 100644
--- a/.env.development
+++ b/.env.development
@@ -2,4 +2,5 @@
ENV = 'development'
# base api
-VUE_APP_BASE_API = '/dev-api'
+#VUE_APP_BASE_API = '/api'
+VUE_APP_BASE_API = 'http://127.0.0.1:8000'
diff --git a/.env.production b/.env.production
index 80c810301f..2bf37ad227 100644
--- a/.env.production
+++ b/.env.production
@@ -2,5 +2,5 @@
ENV = 'production'
# base api
-VUE_APP_BASE_API = '/prod-api'
+VUE_APP_BASE_API = 'https://api.czzhibang.cn:8000'
diff --git a/README-zh.md b/README-zh.md
deleted file mode 100644
index 5b6f7bdf0e..0000000000
--- a/README-zh.md
+++ /dev/null
@@ -1,102 +0,0 @@
-# vue-admin-template
-
-> 这是一个极简的 vue admin 管理后台。它只包含了 Element UI & axios & iconfont & permission control & lint,这些搭建后台必要的东西。
-
-[线上地址](http://panjiachen.github.io/vue-admin-template)
-
-[国内访问](https://panjiachen.gitee.io/vue-admin-template)
-
-目前版本为 `v4.0+` 基于 `vue-cli` 进行构建,若你想使用旧版本,可以切换分支到[tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0),它不依赖 `vue-cli`。
-
-## Extra
-
-如果你想要根据用户角色来动态生成侧边栏和 router,你可以使用该分支[permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control)
-
-## 相关项目
-
-- [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
-
-- [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
-
-- [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template)
-
-- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
-
-写了一个系列的教程配套文章,如何从零构建后一个完整的后台项目:
-
-- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
-- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
-- [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35)
-- [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板,专门针对本项目的文章,算作是一篇文档)](https://juejin.im/post/595b4d776fb9a06bbe7dba56)
-- [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836)
-
-## Build Setup
-
-```bash
-# 克隆项目
-git clone https://github.com/PanJiaChen/vue-admin-template.git
-
-# 进入项目目录
-cd vue-admin-template
-
-# 安装依赖
-npm install
-
-# 建议不要直接使用 cnpm 安装以来,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
-npm install --registry=https://registry.npm.taobao.org
-
-# 启动服务
-npm run dev
-```
-
-浏览器访问 [http://localhost:9528](http://localhost:9528)
-
-## 发布
-
-```bash
-# 构建测试环境
-npm run build:stage
-
-# 构建生产环境
-npm run build:prod
-```
-
-## 其它
-
-```bash
-# 预览发布环境效果
-npm run preview
-
-# 预览发布环境效果 + 静态资源分析
-npm run preview -- --report
-
-# 代码格式检查
-npm run lint
-
-# 代码格式检查并自动修复
-npm run lint -- --fix
-```
-
-更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
-
-## 购买贴纸
-
-你也可以通过 购买[官方授权的贴纸](https://smallsticker.com/product/vue-element-admin) 的方式来支持 vue-element-admin - 每售出一张贴纸,我们将获得 2 元的捐赠。
-
-## Demo
-
-
-
-## Browsers support
-
-Modern browsers and Internet Explorer 10+.
-
-| [
](http://godban.github.io/browsers-support-badges/)IE / Edge | [
](http://godban.github.io/browsers-support-badges/)Firefox | [
](http://godban.github.io/browsers-support-badges/)Chrome | [
](http://godban.github.io/browsers-support-badges/)Safari |
-| --------- | --------- | --------- | --------- |
-| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
-
-## License
-
-[MIT](https://github.com/PanJiaChen/vue-admin-template/blob/master/LICENSE) license.
-
-Copyright (c) 2017-present PanJiaChen
diff --git a/README.md b/README.md
index a2f3c71543..cca820a8f5 100644
--- a/README.md
+++ b/README.md
@@ -1,90 +1,45 @@
-# vue-admin-template
-
-English | [简体中文](./README-zh.md)
-
-> A minimal vue admin template with Element UI & axios & iconfont & permission control & lint
-
-**Live demo:** http://panjiachen.github.io/vue-admin-template
-
-
-**The current version is `v4.0+` build on `vue-cli`. If you want to use the old version , you can switch branch to [tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0), it does not rely on `vue-cli`**
-
-## Build Setup
-
-```bash
-# clone the project
-git clone https://github.com/PanJiaChen/vue-admin-template.git
-
-# enter the project directory
-cd vue-admin-template
-
-# install dependency
-npm install
-
-# develop
-npm run dev
-```
-
-This will automatically open http://localhost:9528
-
-## Build
-
-```bash
-# build for test environment
-npm run build:stage
-
-# build for production environment
-npm run build:prod
-```
-
-## Advanced
-
-```bash
-# preview the release environment effect
-npm run preview
-
-# preview the release environment effect + static resource analysis
-npm run preview -- --report
-
-# code format check
-npm run lint
-
-# code format check and auto fix
-npm run lint -- --fix
-```
-
-Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) for more information
-
-## Demo
-
-
-
-## Extra
-
-If you want router permission && generate menu by user roles , you can use this branch [permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control)
-
-For `typescript` version, you can use [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour))
-
-## Related Project
-
-- [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
-
-- [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
-
-- [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template)
-
-- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
-
-## Browsers support
-
-Modern browsers and Internet Explorer 10+.
-
-| [
](http://godban.github.io/browsers-support-badges/)IE / Edge | [
](http://godban.github.io/browsers-support-badges/)Firefox | [
](http://godban.github.io/browsers-support-badges/)Chrome | [
](http://godban.github.io/browsers-support-badges/)Safari |
-| --------- | --------- | --------- | --------- |
-| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
-
-## License
-
-[MIT](https://github.com/PanJiaChen/vue-admin-template/blob/master/LICENSE) license.
-
-Copyright (c) 2017-present PanJiaChen
+三邦面料系统开发(前端)
+
+fork项目 vue-admin-template
+
+api文档:
+
+1. 用户模块
+1.1 登陆: (/user/login) POST
+请求:{
+ 'username': 用户名,
+ 'password': 密码
+}
+
+返回:
+成功 {
+ 'code': 20000,
+ 'data': {
+ 'token': 密钥
+ }
+}
+失败 {
+ 'code': 60204,
+ ‘message’ : '密码错误'/'没有此用户'/'登录验证错误'+error
+}
+
+
+1.2 获取用户信息 (user/info) GET
+请求:params {token}
+
+返回:
+成功 {
+ 'code': 20000,
+ 'data': {
+ 'data': {
+ 'avatar': 头像,
+ 'name': 姓名,
+ 'position': 职位,
+ 'roles' 权限:
+ }
+ }
+}
+失败 {
+ 'code': 50000,
+ ‘message’ : '登录失败,无法获取用户资料'+error
+}
\ No newline at end of file
diff --git a/mock/index.js b/mock/index.js
deleted file mode 100644
index c514c13573..0000000000
--- a/mock/index.js
+++ /dev/null
@@ -1,57 +0,0 @@
-const Mock = require('mockjs')
-const { param2Obj } = require('./utils')
-
-const user = require('./user')
-const table = require('./table')
-
-const mocks = [
- ...user,
- ...table
-]
-
-// for front mock
-// please use it cautiously, it will redefine XMLHttpRequest,
-// which will cause many of your third-party libraries to be invalidated(like progress event).
-function mockXHR() {
- // mock patch
- // https://github.com/nuysoft/Mock/issues/300
- Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
- Mock.XHR.prototype.send = function() {
- if (this.custom.xhr) {
- this.custom.xhr.withCredentials = this.withCredentials || false
-
- if (this.responseType) {
- this.custom.xhr.responseType = this.responseType
- }
- }
- this.proxy_send(...arguments)
- }
-
- function XHR2ExpressReqWrap(respond) {
- return function(options) {
- let result = null
- if (respond instanceof Function) {
- const { body, type, url } = options
- // https://expressjs.com/en/4x/api.html#req
- result = respond({
- method: type,
- body: JSON.parse(body),
- query: param2Obj(url)
- })
- } else {
- result = respond
- }
- return Mock.mock(result)
- }
- }
-
- for (const i of mocks) {
- Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
- }
-}
-
-module.exports = {
- mocks,
- mockXHR
-}
-
diff --git a/mock/mock-server.js b/mock/mock-server.js
deleted file mode 100644
index 8941ec0f80..0000000000
--- a/mock/mock-server.js
+++ /dev/null
@@ -1,81 +0,0 @@
-const chokidar = require('chokidar')
-const bodyParser = require('body-parser')
-const chalk = require('chalk')
-const path = require('path')
-const Mock = require('mockjs')
-
-const mockDir = path.join(process.cwd(), 'mock')
-
-function registerRoutes(app) {
- let mockLastIndex
- const { mocks } = require('./index.js')
- const mocksForServer = mocks.map(route => {
- return responseFake(route.url, route.type, route.response)
- })
- for (const mock of mocksForServer) {
- app[mock.type](mock.url, mock.response)
- mockLastIndex = app._router.stack.length
- }
- const mockRoutesLength = Object.keys(mocksForServer).length
- return {
- mockRoutesLength: mockRoutesLength,
- mockStartIndex: mockLastIndex - mockRoutesLength
- }
-}
-
-function unregisterRoutes() {
- Object.keys(require.cache).forEach(i => {
- if (i.includes(mockDir)) {
- delete require.cache[require.resolve(i)]
- }
- })
-}
-
-// for mock server
-const responseFake = (url, type, respond) => {
- return {
- url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`),
- type: type || 'get',
- response(req, res) {
- console.log('request invoke:' + req.path)
- res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
- }
- }
-}
-
-module.exports = app => {
- // parse app.body
- // https://expressjs.com/en/4x/api.html#req.body
- app.use(bodyParser.json())
- app.use(bodyParser.urlencoded({
- extended: true
- }))
-
- const mockRoutes = registerRoutes(app)
- var mockRoutesLength = mockRoutes.mockRoutesLength
- var mockStartIndex = mockRoutes.mockStartIndex
-
- // watch files, hot reload mock server
- chokidar.watch(mockDir, {
- ignored: /mock-server/,
- ignoreInitial: true
- }).on('all', (event, path) => {
- if (event === 'change' || event === 'add') {
- try {
- // remove mock routes stack
- app._router.stack.splice(mockStartIndex, mockRoutesLength)
-
- // clear routes cache
- unregisterRoutes()
-
- const mockRoutes = registerRoutes(app)
- mockRoutesLength = mockRoutes.mockRoutesLength
- mockStartIndex = mockRoutes.mockStartIndex
-
- console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
- } catch (error) {
- console.log(chalk.redBright(error))
- }
- }
- })
-}
diff --git a/mock/table.js b/mock/table.js
deleted file mode 100644
index bd0e0133e1..0000000000
--- a/mock/table.js
+++ /dev/null
@@ -1,29 +0,0 @@
-const Mock = require('mockjs')
-
-const data = Mock.mock({
- 'items|30': [{
- id: '@id',
- title: '@sentence(10, 20)',
- 'status|1': ['published', 'draft', 'deleted'],
- author: 'name',
- display_time: '@datetime',
- pageviews: '@integer(300, 5000)'
- }]
-})
-
-module.exports = [
- {
- url: '/vue-admin-template/table/list',
- type: 'get',
- response: config => {
- const items = data.items
- return {
- code: 20000,
- data: {
- total: items.length,
- items: items
- }
- }
- }
- }
-]
diff --git a/mock/user.js b/mock/user.js
deleted file mode 100644
index 7555338562..0000000000
--- a/mock/user.js
+++ /dev/null
@@ -1,84 +0,0 @@
-
-const tokens = {
- admin: {
- token: 'admin-token'
- },
- editor: {
- token: 'editor-token'
- }
-}
-
-const users = {
- 'admin-token': {
- roles: ['admin'],
- introduction: 'I am a super administrator',
- avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
- name: 'Super Admin'
- },
- 'editor-token': {
- roles: ['editor'],
- introduction: 'I am an editor',
- avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
- name: 'Normal Editor'
- }
-}
-
-module.exports = [
- // user login
- {
- url: '/vue-admin-template/user/login',
- type: 'post',
- response: config => {
- const { username } = config.body
- const token = tokens[username]
-
- // mock error
- if (!token) {
- return {
- code: 60204,
- message: 'Account and password are incorrect.'
- }
- }
-
- return {
- code: 20000,
- data: token
- }
- }
- },
-
- // get user info
- {
- url: '/vue-admin-template/user/info\.*',
- type: 'get',
- response: config => {
- const { token } = config.query
- const info = users[token]
-
- // mock error
- if (!info) {
- return {
- code: 50008,
- message: 'Login failed, unable to get user details.'
- }
- }
-
- return {
- code: 20000,
- data: info
- }
- }
- },
-
- // user logout
- {
- url: '/vue-admin-template/user/logout',
- type: 'post',
- response: _ => {
- return {
- code: 20000,
- data: 'success'
- }
- }
- }
-]
diff --git a/mock/utils.js b/mock/utils.js
deleted file mode 100644
index 95cc27d5fe..0000000000
--- a/mock/utils.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * @param {string} url
- * @returns {Object}
- */
-function param2Obj(url) {
- const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
- if (!search) {
- return {}
- }
- const obj = {}
- const searchArr = search.split('&')
- searchArr.forEach(v => {
- const index = v.indexOf('=')
- if (index !== -1) {
- const name = v.substring(0, index)
- const val = v.substring(index + 1, v.length)
- obj[name] = val
- }
- })
- return obj
-}
-
-module.exports = {
- param2Obj
-}
diff --git a/package.json b/package.json
index 24138249e2..8864b17b88 100644
--- a/package.json
+++ b/package.json
@@ -14,16 +14,32 @@
"test:ci": "npm run lint && npm run test:unit"
},
"dependencies": {
+ "@algoz098/audio-recorder": "^0.1.1",
"axios": "0.18.1",
- "core-js": "3.6.5",
+ "babel-plugin-syntax-dynamic-import": "^6.18.0",
+ "core-js": "^3.6.5",
+ "crypto-js": "^4.0.0",
"element-ui": "2.13.2",
+ "fastclick": "^1.0.6",
+ "inline-worker": "^1.1.0",
"js-cookie": "2.2.0",
+ "less-loader": "^7.0.2",
+ "moment": "^2.29.1",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"path-to-regexp": "2.4.0",
+ "push.js": "^1.0.12",
+ "recorderx": "^2.0.2",
+ "screenfull": "^5.0.2",
"vue": "2.6.10",
+ "vue-json-excel": "^0.3.0",
+ "vue-lazyload": "^1.3.3",
+ "vue-mobile-audio": "^0.1.3",
+ "vue-print-nb-z": "^1.1.6",
"vue-router": "3.0.6",
- "vuex": "3.1.0"
+ "vuex": "3.1.0",
+ "webpack-dev-server": "^3.11.0",
+ "worker-loader": "^3.0.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "4.4.4",
@@ -31,24 +47,60 @@
"@vue/cli-plugin-unit-jest": "4.4.4",
"@vue/cli-service": "4.4.4",
"@vue/test-utils": "1.0.0-beta.29",
- "autoprefixer": "9.5.1",
+ "autoprefixer": "^7.1.2",
+ "babel-core": "^6.22.1",
"babel-eslint": "10.1.0",
+ "babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-jest": "23.6.0",
+ "babel-loader": "^7.1.1",
+ "babel-plugin-component": "^1.1.1",
"babel-plugin-dynamic-import-node": "2.3.3",
+ "babel-plugin-syntax-jsx": "^6.18.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",
"chalk": "2.4.2",
"connect": "3.6.6",
+ "copy-webpack-plugin": "^4.0.1",
+ "crypto-js": "^4.0.0",
+ "css-loader": "^0.28.0",
+ "enc": "^0.4.0",
"eslint": "6.7.2",
"eslint-plugin-vue": "6.2.2",
+ "extract-text-webpack-plugin": "^3.0.0",
+ "file-loader": "^1.1.4",
+ "friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "3.2.0",
- "mockjs": "1.0.1-beta3",
+ "node-notifier": "^5.1.2",
+ "optimize-css-assets-webpack-plugin": "^3.2.0",
+ "ora": "^1.2.0",
+ "popper.js": "^1.16.1",
+ "portfinder": "^1.0.13",
+ "postcss-import": "^11.0.0",
+ "postcss-loader": "^2.0.8",
+ "postcss-url": "^7.2.1",
+ "rimraf": "^2.6.0",
"runjs": "4.3.2",
"sass": "1.26.8",
"sass-loader": "8.0.2",
"script-ext-html-webpack-plugin": "2.1.3",
+ "semver": "^5.3.0",
"serve-static": "1.13.2",
+ "shelljs": "^0.7.6",
+ "style-loader": "^1.2.1",
"svg-sprite-loader": "4.1.3",
"svgo": "1.2.2",
- "vue-template-compiler": "2.6.10"
+ "uglifyjs-webpack-plugin": "^1.1.1",
+ "url-loader": "^0.5.8",
+ "vconsole": "^3.3.4",
+ "vue-loader": "^15.9.3",
+ "vue-style-loader": "^3.0.1",
+ "vue-template-compiler": "2.6.10",
+ "webpack": "^4.44.1",
+ "webpack-bundle-analyzer": "^2.9.0",
+ "webpack-cli": "^3.3.12",
+ "webpack-merge": "^4.1.0"
},
"browserslist": [
"> 1%",
diff --git a/public/favicon.ico b/public/favicon.ico
index 34b63ac63a..1175fce245 100644
Binary files a/public/favicon.ico and b/public/favicon.ico differ
diff --git a/src/api/contract/contract_check.js b/src/api/contract/contract_check.js
new file mode 100644
index 0000000000..8856f02350
--- /dev/null
+++ b/src/api/contract/contract_check.js
@@ -0,0 +1,161 @@
+import request from '@/utils/request'
+
+// 合同审核颜色
+export function queryContractCheckColor(data) {
+ return request({
+ url: '/contract_check_color/query',
+ method: 'post',
+ data
+ })
+}
+
+export function addContractCheckColor(data) {
+ return request({
+ url: '/contract_check_color/add',
+ method: 'post',
+ data
+ })
+}
+
+export function modifyContractCheckColor(data) {
+ return request({
+ url: '/contract_check_color/modify',
+ method: 'post',
+ data
+ })
+}
+
+export function deleteContractCheckColor(data) {
+ return request({
+ url: '/contract_check_color/delete',
+ method: 'post',
+ data
+ })
+}
+
+// 合同审核价格
+export function queryContractCheckPrice(data) {
+ return request({
+ url: '/contract_check_price/query',
+ method: 'post',
+ data
+ })
+}
+
+export function queryContractCheckPrice_product(data) {
+ return request({
+ url: '/contract_check_price/product',
+ method: 'post',
+ data
+ })
+}
+
+export function addContractCheckPrice(data) {
+ return request({
+ url: '/contract_check_price/add',
+ method: 'post',
+ data
+ })
+}
+
+export function modifyContractCheckPrice(data) {
+ return request({
+ url: '/contract_check_price/modify',
+ method: 'post',
+ data
+ })
+}
+
+export function deleteContractCheckPrice(data) {
+ return request({
+ url: '/contract_check_price/delete',
+ method: 'post',
+ data
+ })
+}
+
+export function queryMaterialName() {
+ return request({
+ url: '/material/query_name',
+ method: 'get'
+ })
+}
+
+export function queryProvider() {
+ return request({
+ url: '/provider/query_provider',
+ method: 'get'
+ })
+}
+
+export function checkState(data) {
+ return request({
+ url: '/new_contract/check_state',
+ method: 'post',
+ data
+ })
+}
+
+export function unLock(data) {
+ return request({
+ url: '/new_contract/unlock',
+ method: 'post',
+ data
+ })
+}
+
+export function queryContractProduct(data) {
+ return request({
+ url: '/contract_product/query',
+ method: 'post',
+ data
+ })
+}
+
+export function modifyContractProduct(data) {
+ return request({
+ url: '/contract_product/modify',
+ method: 'post',
+ data
+ })
+}
+
+export function addContractProduct(data) {
+ return request({
+ url: '/contract_product/add',
+ method: 'post',
+ data
+ })
+}
+
+export function deleteContractProduct(data) {
+ return request({
+ url: '/contract_product/delete',
+ method: 'post',
+ data
+ })
+}
+
+export function submit_production(data) {
+ return request({
+ url: '/contract_product/submit',
+ method: 'post',
+ data
+ })
+}
+
+export function export_fabric_contract(data) {
+ return request({
+ url: '/excel/fabric_contract',
+ method: 'post',
+ data
+ })
+}
+
+export function export_cloth_contract(data) {
+ return request({
+ url: '/excel/cloth_contract',
+ method: 'post',
+ data
+ })
+}
diff --git a/src/api/contract/new_contract.js b/src/api/contract/new_contract.js
new file mode 100644
index 0000000000..d5e40966e8
--- /dev/null
+++ b/src/api/contract/new_contract.js
@@ -0,0 +1,178 @@
+import request from '@/utils/request'
+
+export function getAllContracts(data) {
+ return request({
+ url: '/new_contract/all',
+ method: 'post',
+ data
+ })
+}
+
+export function queryContracts(data) {
+ return request({
+ url: '/new_contract/query',
+ method: 'post',
+ data
+ })
+}
+
+export function getContractsDetail(data) {
+ return request({
+ url: '/new_contract/detail',
+ method: 'post',
+ data
+ })
+}
+
+export function addContracts(data) {
+ return request({
+ url: '/new_contract/add',
+ method: 'post',
+ data
+ })
+}
+
+export function modifyContracts(data) {
+ return request({
+ url: '/new_contract/modify',
+ method: 'post',
+ data
+ })
+}
+
+export function deleteContracts(data) {
+ return request({
+ url: '/new_contract/delete',
+ method: 'post',
+ data
+ })
+}
+
+export function add_contract_finish(data) {
+ return request({
+ url: '/new_contract/finish',
+ method: 'post',
+ data
+ })
+}
+
+export function querySalesman() {
+ return request({
+ url: '/user/query_salesman',
+ method: 'get'
+ })
+}
+
+export function queryCustomer() {
+ return request({
+ url: '/customer/query_company',
+ method: 'get'
+ })
+}
+
+export function upload(data) {
+ return request({
+ url: '/new_contract/upload',
+ method: 'post',
+ data
+ })
+}
+
+export function query_contract_id(data) {
+ return request({
+ url: '/contract_detail/contract_id',
+ method: 'post',
+ data
+ })
+}
+
+export function query_style_id(data) {
+ return request({
+ url: '/contract_detail/style_id',
+ method: 'post',
+ data
+ })
+}
+
+export function query_style_name(data) {
+ return request({
+ url: '/contract_detail/style_name',
+ method: 'post',
+ data
+ })
+}
+
+export function query_color(data) {
+ return request({
+ url: '/contract_detail/color',
+ method: 'post',
+ data
+ })
+}
+
+export function query_name(data) {
+ return request({
+ url: '/contract_detail/name',
+ method: 'post',
+ data
+ })
+}
+
+export function query_contract_detail(data) {
+ return request({
+ url: '/contract_detail/query',
+ method: 'post',
+ data
+ })
+}
+
+// 合同进度
+export function add_contract_process(data) {
+ return request({
+ url: '/contract_process/add',
+ method: 'post',
+ data
+ })
+}
+
+export function get_contract_process(data) {
+ return request({
+ url: '/contract_process/all',
+ method: 'post',
+ data
+ })
+}
+
+export function delete_contract_process(data) {
+ return request({
+ url: '/contract_process/delete',
+ method: 'post',
+ data
+ })
+}
+
+export function modify_contract_process(data) {
+ return request({
+ url: '/contract_process/modify',
+ method: 'post',
+ data
+ })
+}
+
+// 翻单
+export function repeat(data) {
+ return request({
+ url: '/new_contract/repeat',
+ method: 'post',
+ data
+ })
+}
+
+export function audio_upload(data) {
+ return request({
+ url: '/contract_process/audio_upload',
+ method: 'post',
+ data
+ })
+}
+
diff --git a/src/api/customer.js b/src/api/customer.js
new file mode 100644
index 0000000000..2861bc8357
--- /dev/null
+++ b/src/api/customer.js
@@ -0,0 +1,41 @@
+import request from '@/utils/request'
+
+export function getAllCustomers() {
+ return request({
+ url: '/customer/all',
+ method: 'get'
+ })
+}
+
+export function queryCustomers(data) {
+ return request({
+ url: '/customer/query',
+ method: 'post',
+ data
+ })
+}
+
+export function addCustomers(data) {
+ return request({
+ url: '/customer/add',
+ method: 'post',
+ data
+ })
+}
+
+export function modifyCustomers(data) {
+ return request({
+ url: '/customer/modify',
+ method: 'post',
+ data
+ })
+}
+
+export function deleteCustomers(data) {
+ return request({
+ url: '/customer/delete',
+ method: 'post',
+ data
+ })
+}
+
diff --git a/src/api/finance.js b/src/api/finance.js
new file mode 100644
index 0000000000..fc58e0530a
--- /dev/null
+++ b/src/api/finance.js
@@ -0,0 +1,260 @@
+import request from '@/utils/request'
+// 财务-应付款
+export function get_all_finance_provider() {
+ return request({
+ url: '/finance_provider/all',
+ method: 'get'
+ })
+}
+
+export function query_finance_providers(data) {
+ return request({
+ url: '/finance_provider/query',
+ method: 'post',
+ data
+ })
+}
+
+export function query_storage_details(data) {
+ return request({
+ url: '/finance_provider/storage',
+ method: 'post',
+ data
+ })
+}
+
+export function query_provider_checking(data) {
+ return request({
+ url: '/finance_provider/checking',
+ method: 'post',
+ data
+ })
+}
+
+// 财务-应收款
+export function get_all_finance_customer() {
+ return request({
+ url: '/finance_customer/all',
+ method: 'get'
+ })
+}
+
+export function query_finance_customers(data) {
+ return request({
+ url: '/finance_customer/query',
+ method: 'post',
+ data
+ })
+}
+
+export function unit_price_checked(data) {
+ return request({
+ url: '/finance_customer/unit_price_check',
+ method: 'post',
+ data
+ })
+}
+
+export function query_storage_out_details(data) {
+ return request({
+ url: '/finance_customer/storage',
+ method: 'post',
+ data
+ })
+}
+
+export function received_checked(data) {
+ return request({
+ url: '/finance_customer/received_check',
+ method: 'post',
+ data
+ })
+}
+
+export function get_contract_customer_detail(data) {
+ return request({
+ url: '/finance_customer/detail',
+ method: 'post',
+ data
+ })
+}
+
+export function query_customer_checking(data) {
+ return request({
+ url: '/finance_customer/checking',
+ method: 'post',
+ data
+ })
+}
+
+export function get_contract_provider_detail(data) {
+ return request({
+ url: '/finance_provider/detail',
+ method: 'post',
+ data
+ })
+}
+
+// 扣损/附加费
+export function modify_loss_fee(data) {
+ return request({
+ url: '/finance_provider/loss_fee',
+ method: 'post',
+ data
+ })
+}
+
+export function modify_loss_fee_customer(data) {
+ return request({
+ url: '/finance_customer/loss_fee',
+ method: 'post',
+ data
+ })
+}
+// 付款审核
+export function payment_check(data) {
+ return request({
+ url: '/finance_provider/check',
+ method: 'post',
+ data
+ })
+}
+
+// 付款/收款/开票
+export function query_payment_receipt(data) {
+ return request({
+ url: '/payment_receipt/query',
+ method: 'post',
+ data
+ })
+}
+
+export function add_payment_receipt(data) {
+ return request({
+ url: '/payment_receipt/add',
+ method: 'post',
+ data
+ })
+}
+
+export function modify_payment_receipt(data) {
+ return request({
+ url: '/payment_receipt/modify',
+ method: 'post',
+ data
+ })
+}
+
+export function delete_payment_receipt(data) {
+ return request({
+ url: '/payment_receipt/delete',
+ method: 'post',
+ data
+ })
+}
+export function query_payment_receipt_overall_provider(data) {
+ return request({
+ url: '/payment_receipt/overall',
+ method: 'post',
+ data
+ })
+}
+
+// 付款/收款/开票
+export function query_payment_receipt_customer(data) {
+ return request({
+ url: '/payment_receipt_customer/query',
+ method: 'post',
+ data
+ })
+}
+
+export function add_payment_receipt_customer(data) {
+ return request({
+ url: '/payment_receipt_customer/add',
+ method: 'post',
+ data
+ })
+}
+
+export function modify_payment_receipt_customer(data) {
+ return request({
+ url: '/payment_receipt_customer/modify',
+ method: 'post',
+ data
+ })
+}
+
+export function delete_payment_receipt_customer(data) {
+ return request({
+ url: '/payment_receipt_customer/delete',
+ method: 'post',
+ data
+ })
+}
+
+export function query_payment_receipt_overall_customer(data) {
+ return request({
+ url: '/payment_receipt_customer/overall',
+ method: 'post',
+ data
+ })
+}
+
+// 其他费用
+export function query_otherfee(data) {
+ return request({
+ url: '/other_fee/query',
+ method: 'post',
+ data
+ })
+}
+
+export function add_otherfee(data) {
+ return request({
+ url: '/other_fee/add',
+ method: 'post',
+ data
+ })
+}
+
+export function modify_otherfee(data) {
+ return request({
+ url: '/other_fee/modify',
+ method: 'post',
+ data
+ })
+}
+
+export function delete_otherfee(data) {
+ return request({
+ url: '/other_fee/delete',
+ method: 'post',
+ data
+ })
+}
+
+// 合同核算
+export function query_accounting(data) {
+ return request({
+ url: '/contract_accounting/query',
+ method: 'post',
+ data
+ })
+}
+
+export function other_info(data) {
+ return request({
+ url: '/contract_accounting/other_info',
+ method: 'post',
+ data
+ })
+}
+
+export function modify_discription(data) {
+ return request({
+ url: '/contract_accounting/modify',
+ method: 'post',
+ data
+ })
+}
diff --git a/src/api/material.js b/src/api/material.js
new file mode 100644
index 0000000000..cbccd7147a
--- /dev/null
+++ b/src/api/material.js
@@ -0,0 +1,40 @@
+import request from '@/utils/request'
+
+export function getAllMaterials() {
+ return request({
+ url: '/material/all',
+ method: 'get'
+ })
+}
+
+export function queryMaterials(data) {
+ return request({
+ url: '/material/query',
+ method: 'post',
+ data
+ })
+}
+
+export function addMaterials(data) {
+ return request({
+ url: '/material/add',
+ method: 'post',
+ data
+ })
+}
+
+export function modifyMaterials(data) {
+ return request({
+ url: '/material/modify',
+ method: 'post',
+ data
+ })
+}
+
+export function deleteMaterials(data) {
+ return request({
+ url: '/material/delete',
+ method: 'post',
+ data
+ })
+}
diff --git a/src/api/provider.js b/src/api/provider.js
new file mode 100644
index 0000000000..85656cbd1c
--- /dev/null
+++ b/src/api/provider.js
@@ -0,0 +1,40 @@
+import request from '@/utils/request'
+
+export function getAllProviders() {
+ return request({
+ url: '/provider/all',
+ method: 'get'
+ })
+}
+
+export function queryProviders(data) {
+ return request({
+ url: '/provider/query',
+ method: 'post',
+ data
+ })
+}
+
+export function addProviders(data) {
+ return request({
+ url: '/provider/add',
+ method: 'post',
+ data
+ })
+}
+
+export function modifyProviders(data) {
+ return request({
+ url: '/provider/modify',
+ method: 'post',
+ data
+ })
+}
+
+export function deleteProviders(data) {
+ return request({
+ url: '/provider/delete',
+ method: 'post',
+ data
+ })
+}
diff --git a/src/api/storage.js b/src/api/storage.js
new file mode 100644
index 0000000000..9fd597788c
--- /dev/null
+++ b/src/api/storage.js
@@ -0,0 +1,186 @@
+import request from '@/utils/request'
+
+export function upload_img(data) {
+ return request({
+ url: '/contract_storage/upload_img',
+ method: 'post',
+ data
+ })
+}
+
+export function delete_img(data) {
+ return request({
+ url: '/contract_storage/delete_img',
+ method: 'post',
+ data
+ })
+}
+
+export function query_contract_storage_record(data) {
+ return request({
+ url: '/contract_storage/query',
+ method: 'post',
+ data
+ })
+}
+
+export function add_contract_storage_record(data) {
+ return request({
+ url: '/contract_storage/add',
+ method: 'post',
+ data
+ })
+}
+
+export function modify_contract_storage_record(data) {
+ return request({
+ url: '/contract_storage/modify',
+ method: 'post',
+ data
+ })
+}
+
+export function delete_contract_storage_record(data) {
+ return request({
+ url: '/contract_storage/delete',
+ method: 'post',
+ data
+ })
+}
+
+// 成衣出库一览
+export function query_storage_cloth(data) {
+ return request({
+ url: '/contract_storage/cloth',
+ method: 'post',
+ data
+ })
+}
+
+export function get_storage_cloth() {
+ return request({
+ url: '/contract_storage/cloth_all',
+ method: 'get'
+ })
+}
+
+// 面辅料服饰入库一览
+export function query_storage_fabric_sup(data) {
+ return request({
+ url: '/contract_storage/fabric_sup',
+ method: 'post',
+ data
+ })
+}
+
+export function get_storage_fabric_sup() {
+ return request({
+ url: '/contract_storage/fabric_sup_all',
+ method: 'get'
+ })
+}
+
+// 成衣库存
+export function get_contract_detail(data) {
+ return request({
+ url: '/cloth_stock/contract_detail',
+ method: 'post',
+ data
+ })
+}
+
+export function get_fabric_sup_detail(data) {
+ return request({
+ url: '/fabric_sup_stock/contract_detail',
+ method: 'post',
+ data
+ })
+}
+
+// 仓库
+export function query_warehouse(data) {
+ return request({
+ url: '/warehouse/query',
+ method: 'post',
+ data
+ })
+}
+
+export function add_warehouse(data) {
+ return request({
+ url: '/warehouse/add',
+ method: 'post',
+ data
+ })
+}
+
+export function modify_warehouse(data) {
+ return request({
+ url: '/warehouse/modify',
+ method: 'post',
+ data
+ })
+}
+
+export function delete_warehouse(data) {
+ return request({
+ url: '/warehouse/delete',
+ method: 'post',
+ data
+ })
+}
+
+export function get_warehouse_label() {
+ return request({
+ url: '/warehouse/label',
+ method: 'get'
+ })
+}
+
+export function add_stock_record(data) {
+ return request({
+ url: '/stock_record/add',
+ method: 'post',
+ data
+ })
+}
+
+export function modify_stock_record(data) {
+ return request({
+ url: '/stock_record/modify',
+ method: 'post',
+ data
+ })
+}
+
+export function delete_stock_record(data) {
+ return request({
+ url: '/stock_record/delete',
+ method: 'post',
+ data
+ })
+}
+
+export function delete_stock_record_overall(data) {
+ return request({
+ url: '/stock_record_overall/delete',
+ method: 'post',
+ data
+ })
+}
+
+export function query_stock_record_overall(data) {
+ return request({
+ url: '/stock_record_overall/query',
+ method: 'post',
+ data
+ })
+}
+
+export function query_stock_records(data) {
+ return request({
+ url: '/stock_record/query',
+ method: 'post',
+ data
+ })
+}
diff --git a/src/api/user.js b/src/api/user.js
index 8ff4389dba..63fd9c2ca7 100644
--- a/src/api/user.js
+++ b/src/api/user.js
@@ -2,7 +2,7 @@ import request from '@/utils/request'
export function login(data) {
return request({
- url: '/vue-admin-template/user/login',
+ url: '/user/login',
method: 'post',
data
})
@@ -10,7 +10,7 @@ export function login(data) {
export function getInfo(token) {
return request({
- url: '/vue-admin-template/user/info',
+ url: '/user/info',
method: 'get',
params: { token }
})
@@ -18,7 +18,132 @@ export function getInfo(token) {
export function logout() {
return request({
- url: '/vue-admin-template/user/logout',
+ url: '/user/logout',
method: 'post'
})
}
+
+export function ActiveRouter(token) {
+ return request({
+ url: '/group/subMenu',
+ method: 'get',
+ params: { token }
+ })
+}
+
+export function getAllUsers() {
+ return request({
+ url: '/user/all',
+ method: 'get'
+ })
+}
+
+export function queryUsers(data) {
+ return request({
+ url: '/user/query',
+ method: 'post',
+ data
+ })
+}
+
+export function addUsers(data) {
+ return request({
+ url: '/user/add',
+ method: 'post',
+ data
+ })
+}
+
+export function modifyUsers(data) {
+ return request({
+ url: '/user/modify',
+ method: 'post',
+ data
+ })
+}
+
+export function deleteUsers(data) {
+ return request({
+ url: '/user/delete',
+ method: 'post',
+ data
+ })
+}
+
+// export function getUserRole(data) {
+// return request({
+// url: '/user/query_role',
+// method: 'post',
+// data
+// })
+// }
+
+// 用户组
+export function getAllGroups() {
+ return request({
+ url: '/group/all',
+ method: 'get'
+ })
+}
+
+export function modifyGroupUser() {
+ return request({
+ url: '/group/modifyUser',
+ method: 'post'
+ })
+}
+
+export function upload(data) {
+ return request({
+ url: '/user/upload',
+ method: 'post',
+ data
+ })
+}
+
+export function modifypasswd(data) {
+ return request({
+ url: '/user/modifypasswd',
+ method: 'post',
+ data
+ })
+}
+
+export function query_msg(data) {
+ return request({
+ url: '/user/msg',
+ method: 'post',
+ data
+ })
+}
+
+export function clear_msg(data) {
+ return request({
+ url: '/user/clear_msg',
+ method: 'post',
+ data
+ })
+}
+
+// 查询错误
+export function error_query() {
+ return request({
+ url: '/error/query',
+ method: 'get'
+ })
+}
+
+export function error_delete() {
+ return request({
+ url: '/error/delete',
+ method: 'get'
+ })
+}
+
+// 获取业务员
+export function query_salesman() {
+ return request({
+ url: '/user/query_salesman',
+ method: 'get'
+ })
+}
diff --git a/src/assets/ic_record.gif b/src/assets/ic_record.gif
new file mode 100644
index 0000000000..fe67dad549
Binary files /dev/null and b/src/assets/ic_record.gif differ
diff --git a/src/assets/ic_release_to_cancel.png b/src/assets/ic_release_to_cancel.png
new file mode 100644
index 0000000000..de9672cc3d
Binary files /dev/null and b/src/assets/ic_release_to_cancel.png differ
diff --git a/src/assets/timg.gif b/src/assets/timg.gif
new file mode 100644
index 0000000000..c837bff694
Binary files /dev/null and b/src/assets/timg.gif differ
diff --git a/src/components/IatRecorder/index.js b/src/components/IatRecorder/index.js
new file mode 100644
index 0000000000..988857404a
--- /dev/null
+++ b/src/components/IatRecorder/index.js
@@ -0,0 +1,541 @@
+/**
+ * Created by lycheng on 2019/8/1.
+ *
+ * 语音听写流式 WebAPI 接口调用示例 接口文档(必看):https://doc.xfyun.cn/rest_api/语音听写(流式版).html
+ * webapi 听写服务参考帖子(必看):http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=38947&extra=
+ * 语音听写流式WebAPI 服务,热词使用方式:登陆开放平台https://www.xfyun.cn/后,找到控制台--我的应用---语音听写---个性化热词,上传热词
+ * 注意:热词只能在识别的时候会增加热词的识别权重,需要注意的是增加相应词条的识别率,但并不是绝对的,具体效果以您测试为准。
+ * 错误码链接:
+ * https://www.xfyun.cn/doc/asr/voicedictation/API.html#%E9%94%99%E8%AF%AF%E7%A0%81
+ * https://www.xfyun.cn/document/error-code (code返回错误码时必看)
+ * 语音听写流式WebAPI 服务,方言或小语种试用方法:登陆开放平台https://www.xfyun.cn/后,在控制台--语音听写(流式)--方言/语种处添加
+ * 添加后会显示该方言/语种的参数值
+ *
+ */
+
+// 1. websocket连接:判断浏览器是否兼容,获取websocket url并连接,这里为了方便本地生成websocket url
+// 2. 获取浏览器录音权限:判断浏览器是否兼容,获取浏览器录音权限,
+// 3. js获取浏览器录音数据
+// 4. 将录音数据处理为文档要求的数据格式:采样率16k或8K、位长16bit、单声道;该操作属于纯数据处理,使用webWork处理
+// 5. 根据要求(采用base64编码,每次发送音频间隔40ms,每次发送音频字节数1280B)将处理后的数据通过websocket传给服务器,
+// 6. 实时接收websocket返回的数据并进行处理
+
+// ps: 该示例用到了es6中的一些语法,建议在chrome下运行
+
+import CryptoJS from 'crypto-js'
+import TransWorker from './transcode2.worker.js'
+// import './index.css'
+// import {getAuthUrl} from '@/api/websocketUrl.js'
+
+// const transWorker = new Worker('./transcode2.worker.js')
+const transWorker = new TransWorker()
+// console.log(transWorker)
+// APPID,APISecret,APIKey在控制台-我的应用-语音听写(流式版)页面获取
+const APPID = '5fc43f4e'
+const API_SECRET = '36bed5c0abb02f5b27a5331188f3af08'
+const API_KEY = 'b46fa3a731604783f3dc141b4e63628c'
+var startTime = ''
+var endTime = ''
+
+/**
+ * 获取websocket url
+ * 该接口需要后端提供,这里为了方便前端处理
+ */
+function getWebSocketUrl() {
+ return new Promise((resolve, reject) => {
+ // 请求地址根据语种不同变化
+ var url = 'wss://iat-api.xfyun.cn/v2/iat'
+ var host = 'iat-api.xfyun.cn'
+ var apiKey = API_KEY
+ var apiSecret = API_SECRET
+ var date = new Date().toGMTString()
+ var algorithm = 'hmac-sha256'
+ var headers = 'host date request-line'
+ var signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v2/iat HTTP/1.1`
+ var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret)
+ var signature = CryptoJS.enc.Base64.stringify(signatureSha)
+ var authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`
+ var authorization = btoa(authorizationOrigin)
+ url = `${url}?authorization=${authorization}&date=${date}&host=${host}`
+ resolve(url)
+ })
+}
+
+class IatRecorder {
+ constructor({ language, accent, appId } = {}) {
+ const self = this
+ this.status = 'null'
+ this.language = language || 'zh_cn'
+ this.accent = accent || 'mandarin'
+ this.appId = appId || APPID
+ // 记录音频数据
+ this.audioData = []
+ // 记录听写结果
+ this.resultText = ''
+ // 保存录音
+ this.leftDataList = []
+ this.rightDataList = []
+ // 保存录音 end
+ // wpgs下的听写结果需要中间状态辅助记录
+
+ this.resultTextTemp = ''
+ this.stream_track = null
+ transWorker.onmessage = function(event) {
+ // console.log('构造方法中', self.audioData)
+ self.audioData.push(...event.data)
+ }
+ }
+ // 修改录音听写状态
+ setStatus(status) {
+ this.onWillStatusChange && this.status !== status && this.onWillStatusChange(this.status, status)
+ this.status = status
+ }
+ setResultText({ resultText, resultTextTemp } = {}) {
+ // console.log(resultText + '-----' + resultTextTemp)
+ this.onTextChange && this.onTextChange(resultTextTemp || resultText || '')
+ resultText !== undefined && (this.resultText = resultText)
+ resultTextTemp !== undefined && (this.resultTextTemp = resultTextTemp)
+ }
+ // 修改听写参数
+ setParams({ language, accent } = {}) {
+ language && (this.language = language)
+ accent && (this.accent = accent)
+ }
+ // 连接websocket
+ connectWebSocket() {
+ return getWebSocketUrl().then(url => {
+ let iatWS
+ if ('WebSocket' in window) {
+ iatWS = new WebSocket(url)
+ } else {
+ alert('浏览器不支持WebSocket')
+ return
+ }
+ this.webSocket = iatWS
+ this.setStatus('init')
+ iatWS.onopen = e => {
+ this.setStatus('ing')
+ // 重新开始录音
+ setTimeout(() => {
+ this.webSocketSend()
+ }, 500)
+ }
+ iatWS.onmessage = e => {
+ this.result(e.data)
+ }
+ iatWS.onerror = e => {
+ this.recorderStop()
+ }
+ iatWS.onclose = e => {
+ endTime = Date.parse(new Date())
+ console.log('持续时间', endTime - startTime)
+ this.recorderStop()
+ }
+ })
+ }
+ getUserMedia(constrains) {
+ if (navigator.mediaDevices.getUserMedia) {
+ // 最新标准API
+ navigator.mediaDevices.getUserMedia(constrains).then(stream => { this.getMediaSuccess(stream) }).catch(err => { this.getMediaFail(err) })
+ } else if (navigator.webkitGetUserMedia) {
+ // webkit内核浏览器
+ navigator.webkitGetUserMedia(constrains).then(stream => { this.getMediaSuccess(stream) }).catch(err => { this.getMediaFail(err) })
+ } else if (navigator.mozGetUserMedia) {
+ // Firefox浏览器
+ navigator.mozGetUserMedia(constrains).then(stream => { this.getMediaSuccess(stream) }).catch(err => { this.getMediaFail(err) })
+ } else if (navigator.getUserMedia) {
+ // 旧版API
+ navigator.getUserMedia(constrains).then(stream => { this.getMediaSuccess(stream) }).catch(err => { this.getMediaFail(err) })
+ } else {
+ if (navigator.userAgent.toLowerCase().match(/chrome/) && location.origin.indexOf('https://') < 0) {
+ alert('chrome下获取浏览器录音功能,因为安全性问题,需要在localhost或127.0.0.1或https下才能获取权限')
+ } else {
+ alert('无法获取浏览器录音功能,请升级浏览器或使用chrome')
+ }
+ this.audioContext && this.audioContext.close()
+ return
+ }
+ }
+ // 初始化浏览器录音
+ recorderInit() {
+ navigator.getUserMedia =
+ navigator.getUserMedia ||
+ navigator.webkitGetUserMedia ||
+ navigator.mozGetUserMedia ||
+ navigator.msGetUserMedia
+
+ // 创建音频环境
+ try {
+ this.audioContext = new (window.AudioContext || window.webkitAudioContext)()
+ this.audioContext.resume()
+ if (!this.audioContext) {
+ alert('浏览器不支持webAudioApi相关接口')
+ return
+ }
+ } catch (e) {
+ if (!this.audioContext) {
+ alert('浏览器不支持webAudioApi相关接口')
+ return
+ }
+ }
+ // console.log(navigator, navigator.mediaDevices)
+ // 获取浏览器录音权限
+
+ // if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
+ // // console.log(navigator)
+ // navigator.mediaDevices
+ // .getUserMedia({
+ // audio: true,
+ // video: false
+ // })
+ // .then(stream => {
+ // // console.log(stream)
+ // getMediaSuccess(stream)
+ // })
+ // .catch(e => {
+ // getMediaFail(e)
+ // })
+ // } else if (navigator.getUserMedia) {
+ // navigator.getUserMedia(
+ // {
+ // audio: true,
+ // video: false
+ // },
+ // stream => {
+ // getMediaSuccess(stream)
+ // },
+ // function(e) {
+ // getMediaFail(e)
+ // }
+ // )
+ // } else {
+ // if (navigator.userAgent.toLowerCase().match(/chrome/) && location.origin.indexOf('https://') < 0) {
+ // alert('chrome下获取浏览器录音功能,因为安全性问题,需要在localhost或127.0.0.1或https下才能获取权限')
+ // } else {
+ // alert('无法获取浏览器录音功能,请升级浏览器或使用chrome')
+ // }
+ // this.audioContext && this.audioContext.close()
+ // return
+ // }
+ const constrains = { audio: true }
+ if (navigator.mediaDevices.getUserMedia) {
+ // 最新标准API
+ navigator.mediaDevices.getUserMedia(constrains).then(stream => { getMediaSuccess(stream) }).catch(err => { getMediaFail(err) })
+ } else if (navigator.webkitGetUserMedia) {
+ // webkit内核浏览器
+ navigator.webkitGetUserMedia(constrains).then(stream => { getMediaSuccess(stream) }).catch(err => { getMediaFail(err) })
+ } else if (navigator.mozGetUserMedia) {
+ // Firefox浏览器
+ navigator.mozGetUserMedia(constrains).then(stream => { getMediaSuccess(stream) }).catch(err => { getMediaFail(err) })
+ } else if (navigator.getUserMedia) {
+ // 旧版API
+ navigator.getUserMedia(constrains).then(stream => { getMediaSuccess(stream) }).catch(err => { getMediaFail(err) })
+ } else {
+ if (navigator.userAgent.toLowerCase().match(/chrome/) && location.origin.indexOf('https://') < 0) {
+ alert('chrome下获取浏览器录音功能,因为安全性问题,需要在localhost或127.0.0.1或https下才能获取权限')
+ } else {
+ alert('无法获取浏览器录音功能,请升级浏览器或使用chrome')
+ }
+ this.audioContext && this.audioContext.close()
+ return
+ }
+ var that = this
+ // 获取浏览器录音权限成功的回调
+ const getMediaSuccess = stream => {
+ // console.log('getMediaSuccess')
+ // 创建一个用于通过JavaScript直接处理音频
+ // 新增保存录音
+
+ // 新增保存录音end
+ this.scriptProcessor = this.audioContext.createScriptProcessor(4096, 2, 2)
+ // 保存录音
+
+ // 保存录音 end
+ this.scriptProcessor.onaudioprocess = e => {
+ // 去处理音频数据
+ if (this.status === 'ing') {
+ // debugger
+ transWorker.postMessage(e.inputBuffer.getChannelData(0))
+ // 保存录音
+
+ const leftChannelData = e.inputBuffer.getChannelData(0)
+ const rightChannelData = e.inputBuffer.getChannelData(1)
+ // 需要克隆一下
+ that.leftDataList.push(leftChannelData.slice(0))
+ that.rightDataList.push(rightChannelData.slice(0))
+
+ // 保存录音 end
+ }
+ }
+ // 创建一个新的MediaStreamAudioSourceNode 对象,使来自MediaStream的音频可以被播放和操作
+ this.mediaSource = this.audioContext.createMediaStreamSource(stream)
+ // 连接
+ this.stream_track = stream.getTracks()[0]
+ this.mediaSource.connect(this.scriptProcessor)
+ this.scriptProcessor.connect(this.audioContext.destination)
+ this.connectWebSocket()
+ }
+
+ const getMediaFail = (e) => {
+ alert('请求麦克风失败')
+ console.log(e)
+ this.audioContext && this.audioContext.close()
+ this.audioContext = undefined
+ // 关闭websocket
+ if (this.webSocket && this.webSocket.readyState === 1) {
+ this.webSocket.close()
+ }
+ }
+ }
+ recorderStart() {
+ if (!this.audioContext) {
+ this.recorderInit()
+ console.log('录音初始化')
+ } else {
+ this.audioContext.resume()
+ console.log('继续录音')
+ this.connectWebSocket()
+ }
+ }
+ // 暂停录音
+ recorderStop() {
+ // safari下suspend后再次resume录音内容将是空白,设置safari下不做suspend
+ if (!(/Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgen))) {
+ this.audioContext && this.audioContext.suspend()
+ }
+ // console.log('audioContext', this.audioContext)
+ this.setStatus('end')
+ // this.stream_track.stop()
+ // 发送语音并保存点击播放
+ if (this.leftDataList.length !== 0) {
+ this.stopRecord(this.leftDataList, this.rightDataList)
+ }
+ return this.stream_track
+ }
+ //
+ mergeArray(list) {
+ const length = list.length * list[0].length
+ const data = new Float32Array(length)
+ let offset = 0
+ for (let i = 0; i < list.length; i++) {
+ data.set(list[i], offset)
+ offset += list[i].length
+ }
+ return data
+ }
+ stopRecord(leftDataList, rightDataList) {
+ // 停止录音
+ const leftData = this.mergeArray(leftDataList)
+ const rightData = this.mergeArray(rightDataList)
+ const audioData = this.interleaveLeftAndRight(leftData, rightData)
+ const wavBuffer = this.createWavFile(audioData)
+ this.playRecord(wavBuffer)
+ }
+ interleaveLeftAndRight(left, right) {
+ const totalLength = left.length + right.length
+ const data = new Float32Array(totalLength)
+ for (let i = 0; i < left.length; i++) {
+ const k = i * 2
+ data[k] = left[i]
+ data[k + 1] = right[i]
+ }
+ return data
+ }
+ createWavFile(audioData) {
+ // console.log(this.audioData, this.audioContext)
+ const WAV_HEAD_SIZE = 44
+ const buffer = new ArrayBuffer(audioData.length * 2 + WAV_HEAD_SIZE)
+ // 需要用一个view来操控buffer
+ const view = new DataView(buffer)
+ // 写入wav头部信息
+ // RIFF chunk descriptor/identifier
+ this.writeUTFBytes(view, 0, 'RIFF')
+ // RIFF chunk length
+ view.setUint32(4, 44 + audioData.length * 2, true)
+ // RIFF type
+ this.writeUTFBytes(view, 8, 'WAVE')
+ // format chunk identifier
+ // FMT sub-chunk
+ this.writeUTFBytes(view, 12, 'fmt ')
+ // format chunk length
+ view.setUint32(16, 16, true)
+ // sample format (raw)
+ view.setUint16(20, 1, true)
+ // stereo (2 channels)
+ view.setUint16(22, 2, true)
+ // sample rate
+ view.setUint32(24, 48000, true)
+ // byte rate (sample rate * block align)
+ view.setUint32(28, 48000 * 2, true)
+ // block align (channel count * bytes per sample)
+ view.setUint16(32, 2 * 2, true)
+ // bits per sample
+ view.setUint16(34, 16, true)
+ // data sub-chunk
+ // data chunk identifier
+ this.writeUTFBytes(view, 36, 'data')
+ // data chunk length
+ view.setUint32(40, audioData.length * 2, true)
+ // 写入PCM数据
+ const length = audioData.length
+ let index = 44
+ const volume = 1
+ for (let i = 0; i < length; i++) {
+ view.setInt16(index, audioData[i] * (0x7FFF * volume), true)
+ index += 2
+ }
+ return buffer
+ }
+ writeUTFBytes(view, offset, string) {
+ var lng = string.length
+ for (var i = 0; i < lng; i++) {
+ view.setUint8(offset + i, string.charCodeAt(i))
+ }
+ }
+ playRecord(arrayBuffer) {
+ const blob = new Blob([new Uint8Array(arrayBuffer)], { type: 'audio/wav' })
+ // console.log(blob)
+ const blobUrl = URL.createObjectURL(blob)
+ localStorage.setItem('audioURLnew', blobUrl)
+ console.log('保存成功')
+ this.leftDataList = []
+ this.rightDataList = []
+ }
+ // 处理音频数据
+ // transAudioData(audioData) {
+ // audioData = transAudioData.transaction(audioData)
+ // this.audioData.push(...audioData)
+ // }
+ // 对处理后的音频数据进行base64编码,
+ toBase64(buffer) {
+ var binary = ''
+ var bytes = new Uint8Array(buffer)
+ var len = bytes.byteLength
+ for (var i = 0; i < len; i++) {
+ binary += String.fromCharCode(bytes[i])
+ }
+ return window.btoa(binary)
+ }
+ // 向webSocket发送数据
+ webSocketSend() {
+ if (this.webSocket.readyState !== 1) {
+ return
+ }
+ let audioData = this.audioData.splice(0, 1280)
+ var params = {
+ common: {
+ app_id: this.appId
+ },
+ business: {
+ language: this.language, // 小语种可在控制台--语音听写(流式)--方言/语种处添加试用
+ domain: 'iat',
+ accent: this.accent, // 中文方言可在控制台--语音听写(流式)--方言/语种处添加试用
+ vad_eos: 5000,
+ dwa: 'wpgs' // 为使该功能生效,需到控制台开通动态修正功能(该功能免费)
+ },
+ data: {
+ status: 0,
+ format: 'audio/L16;rate=16000',
+ encoding: 'raw',
+ audio: this.toBase64(audioData)
+ }
+ }
+ console.log('参数language:', this.language)
+ console.log('参数accent:', this.accent)
+ startTime = Date.parse(new Date())
+ this.webSocket.send(JSON.stringify(params))
+ this.handlerInterval = setInterval(() => {
+ // websocket未连接
+ if (this.webSocket.readyState !== 1) {
+ console.log('websocket未连接')
+ this.audioData = []
+ clearInterval(this.handlerInterval)
+ return
+ }
+ if (this.audioData.length === 0) {
+ console.log('自动关闭', this.status)
+ if (this.status === 'end') {
+ this.webSocket.send(
+ JSON.stringify({
+ data: {
+ status: 2,
+ format: 'audio/L16;rate=16000',
+ encoding: 'raw',
+ audio: ''
+ }
+ })
+ )
+ this.audioData = []
+ clearInterval(this.handlerInterval)
+ }
+ return false
+ }
+ audioData = this.audioData.splice(0, 1280)
+ // 中间帧
+ // localStorage.setItem('voiceFun', 'on')
+ this.webSocket.send(
+ JSON.stringify({
+ data: {
+ status: 1,
+ format: 'audio/L16;rate=16000',
+ encoding: 'raw',
+ audio: this.toBase64(audioData)
+ }
+ })
+ )
+ }, 40)
+ }
+ result(resultData) {
+ // 识别结束
+ // localStorage.setItem('voiceFun', 'on')
+ const jsonData = JSON.parse(resultData)
+ if (jsonData.data && jsonData.data.result) {
+ const data = jsonData.data.result
+ let str = ''
+ // const resultStr = ''
+ const ws = data.ws
+ for (let i = 0; i < ws.length; i++) {
+ str = str + ws[i].cw[0].w
+ }
+ console.log('识别的结果为:', str)
+ // 开启wpgs会有此字段(前提:在控制台开通动态修正功能)
+ // 取值为 "apd"时表示该片结果是追加到前面的最终结果;取值为"rpl" 时表示替换前面的部分结果,替换范围为rg字段
+ if (data.pgs) {
+ if (data.pgs === 'apd') {
+ // 将resultTextTemp同步给resultText
+ this.setResultText({
+ resultText: this.resultTextTemp
+ })
+ }
+ // 将结果存储在resultTextTemp中
+ this.setResultText({
+ resultTextTemp: this.resultText + str
+ })
+ } else {
+ this.setResultText({
+ resultText: this.resultText + str
+ })
+ }
+ }
+ if (jsonData.code === 0 && jsonData.data.status === 2) {
+ this.webSocket.close()
+ localStorage.setItem('voiceFun', 'off')
+ }
+ if (jsonData.code !== 0) {
+ this.webSocket.close()
+ localStorage.setItem('voiceFun', 'off')
+ }
+ }
+ start() {
+ localStorage.setItem('voiceFun', 'on')
+ this.recorderStart()
+ this.setResultText({ resultText: '', resultTextTemp: '' })
+ }
+ stop() {
+ return this.recorderStop()
+ }
+}
+
+export {
+ IatRecorder
+}
diff --git a/src/components/IatRecorder/transcode.worker.js b/src/components/IatRecorder/transcode.worker.js
new file mode 100644
index 0000000000..88cf7de3cb
--- /dev/null
+++ b/src/components/IatRecorder/transcode.worker.js
@@ -0,0 +1,47 @@
+/*
+ * @Autor: lycheng
+ * @Date: 2020-01-07 08:51:50
+ */
+
+(function() {
+ self.onmessage = function(e) {
+ transAudioData.transcode(e.data)
+ }
+
+ const transAudioData = {
+ transcode(audioData) {
+ let output = transAudioData.to16kHz(audioData)
+ output = transAudioData.to16BitPCM(output)
+ output = Array.from(new Uint8Array(output.buffer))
+ self.postMessage(output)
+ // return output
+ },
+ to16kHz(audioData) {
+ var data = new Float32Array(audioData)
+ var fitCount = Math.round(data.length * (16000 / 44100))
+ var newData = new Float32Array(fitCount)
+ var springFactor = (data.length - 1) / (fitCount - 1)
+ newData[0] = data[0]
+ for (let i = 1; i < fitCount - 1; i++) {
+ var tmp = i * springFactor
+ var before = Math.floor(tmp).toFixed()
+ var after = Math.ceil(tmp).toFixed()
+ var atPoint = tmp - before
+ newData[i] = data[before] + (data[after] - data[before]) * atPoint
+ }
+ newData[fitCount - 1] = data[data.length - 1]
+ return newData
+ },
+ to16BitPCM(input) {
+ var dataLength = input.length * (16 / 8)
+ var dataBuffer = new ArrayBuffer(dataLength)
+ var dataView = new DataView(dataBuffer)
+ var offset = 0
+ for (var i = 0; i < input.length; i++, offset += 2) {
+ var s = Math.max(-1, Math.min(1, input[i]))
+ dataView.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true)
+ }
+ return dataView
+ }
+ }
+})()
diff --git a/src/components/IatRecorder/transcode2.worker.js b/src/components/IatRecorder/transcode2.worker.js
new file mode 100644
index 0000000000..3b25c04a24
--- /dev/null
+++ b/src/components/IatRecorder/transcode2.worker.js
@@ -0,0 +1,40 @@
+
+self.onmessage = function(e) {
+ transAudioData.transcode(e.data)
+}
+const transAudioData = {
+ transcode(audioData) {
+ let output = transAudioData.to16kHz(audioData)
+ output = transAudioData.to16BitPCM(output)
+ output = Array.from(new Uint8Array(output.buffer))
+ self.postMessage(output)
+ // return output
+ },
+ to16kHz(audioData) {
+ var data = new Float32Array(audioData)
+ var fitCount = Math.round(data.length * (16000 / 44100))
+ var newData = new Float32Array(fitCount)
+ var springFactor = (data.length - 1) / (fitCount - 1)
+ newData[0] = data[0]
+ for (let i = 1; i < fitCount - 1; i++) {
+ var tmp = i * springFactor
+ var before = Math.floor(tmp).toFixed()
+ var after = Math.ceil(tmp).toFixed()
+ var atPoint = tmp - before
+ newData[i] = data[before] + (data[after] - data[before]) * atPoint
+ }
+ newData[fitCount - 1] = data[data.length - 1]
+ return newData
+ },
+ to16BitPCM(input) {
+ var dataLength = input.length * (16 / 8)
+ var dataBuffer = new ArrayBuffer(dataLength)
+ var dataView = new DataView(dataBuffer)
+ var offset = 0
+ for (var i = 0; i < input.length; i++, offset += 2) {
+ var s = Math.max(-1, Math.min(1, input[i]))
+ dataView.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true)
+ }
+ return dataView
+ }
+}
diff --git a/src/components/Screenfull/index.vue b/src/components/Screenfull/index.vue
new file mode 100644
index 0000000000..c898b65c33
--- /dev/null
+++ b/src/components/Screenfull/index.vue
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/directives/el-drag-dialog/drag.js b/src/directives/el-drag-dialog/drag.js
new file mode 100644
index 0000000000..299e985440
--- /dev/null
+++ b/src/directives/el-drag-dialog/drag.js
@@ -0,0 +1,77 @@
+export default {
+ bind(el, binding, vnode) {
+ const dialogHeaderEl = el.querySelector('.el-dialog__header')
+ const dragDom = el.querySelector('.el-dialog')
+ dialogHeaderEl.style.cssText += ';cursor:move;'
+ dragDom.style.cssText += ';top:0px;'
+
+ // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
+ const getStyle = (function() {
+ if (window.document.currentStyle) {
+ return (dom, attr) => dom.currentStyle[attr]
+ } else {
+ return (dom, attr) => getComputedStyle(dom, false)[attr]
+ }
+ })()
+
+ dialogHeaderEl.onmousedown = (e) => {
+ // 鼠标按下,计算当前元素距离可视区的距离
+ const disX = e.clientX - dialogHeaderEl.offsetLeft
+ const disY = e.clientY - dialogHeaderEl.offsetTop
+
+ const dragDomWidth = dragDom.offsetWidth
+ const dragDomHeight = dragDom.offsetHeight
+
+ const screenWidth = document.body.clientWidth
+ const screenHeight = document.body.clientHeight
+
+ const minDragDomLeft = dragDom.offsetLeft
+ const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
+
+ const minDragDomTop = dragDom.offsetTop
+ const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight
+
+ // 获取到的值带px 正则匹配替换
+ let styL = getStyle(dragDom, 'left')
+ let styT = getStyle(dragDom, 'top')
+
+ if (styL.includes('%')) {
+ styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
+ styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
+ } else {
+ styL = +styL.replace(/\px/g, '')
+ styT = +styT.replace(/\px/g, '')
+ }
+
+ document.onmousemove = function(e) {
+ // 通过事件委托,计算移动的距离
+ let left = e.clientX - disX
+ let top = e.clientY - disY
+
+ // 边界处理
+ if (-(left) > minDragDomLeft) {
+ left = -minDragDomLeft
+ } else if (left > maxDragDomLeft) {
+ left = maxDragDomLeft
+ }
+
+ if (-(top) > minDragDomTop) {
+ top = -minDragDomTop
+ } else if (top > maxDragDomTop) {
+ top = maxDragDomTop
+ }
+
+ // 移动当前元素
+ dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
+
+ // emit onDrag event
+ vnode.child.$emit('dragDialog')
+ }
+
+ document.onmouseup = function(e) {
+ document.onmousemove = null
+ document.onmouseup = null
+ }
+ }
+ }
+}
diff --git a/src/directives/el-drag-dialog/index.js b/src/directives/el-drag-dialog/index.js
new file mode 100644
index 0000000000..29facbfb3e
--- /dev/null
+++ b/src/directives/el-drag-dialog/index.js
@@ -0,0 +1,13 @@
+import drag from './drag'
+
+const install = function(Vue) {
+ Vue.directive('el-drag-dialog', drag)
+}
+
+if (window.Vue) {
+ window['el-drag-dialog'] = drag
+ Vue.use(install); // eslint-disable-line
+}
+
+drag.install = install
+export default drag
diff --git a/src/icons/svg/exit-fullscreen.svg b/src/icons/svg/exit-fullscreen.svg
new file mode 100644
index 0000000000..485c128b61
--- /dev/null
+++ b/src/icons/svg/exit-fullscreen.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/svg/finance.svg b/src/icons/svg/finance.svg
new file mode 100644
index 0000000000..d15a77236c
--- /dev/null
+++ b/src/icons/svg/finance.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/svg/finance_in.svg b/src/icons/svg/finance_in.svg
new file mode 100644
index 0000000000..eddeaea529
--- /dev/null
+++ b/src/icons/svg/finance_in.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/svg/finance_out.svg b/src/icons/svg/finance_out.svg
new file mode 100644
index 0000000000..58a78f7a5d
--- /dev/null
+++ b/src/icons/svg/finance_out.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/svg/fullscreen.svg b/src/icons/svg/fullscreen.svg
new file mode 100644
index 0000000000..0e86b6fa80
--- /dev/null
+++ b/src/icons/svg/fullscreen.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/svg/material.svg b/src/icons/svg/material.svg
new file mode 100644
index 0000000000..c84b8d07fa
--- /dev/null
+++ b/src/icons/svg/material.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/svg/provider.svg b/src/icons/svg/provider.svg
new file mode 100644
index 0000000000..b62538ba97
--- /dev/null
+++ b/src/icons/svg/provider.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/svg/storage.svg b/src/icons/svg/storage.svg
new file mode 100644
index 0000000000..527b5a2c13
--- /dev/null
+++ b/src/icons/svg/storage.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/layout/components/AppMain.vue b/src/layout/components/AppMain.vue
index f6a3286f58..b3a8011b6f 100644
--- a/src/layout/components/AppMain.vue
+++ b/src/layout/components/AppMain.vue
@@ -1,7 +1,15 @@
@@ -10,23 +18,42 @@
export default {
name: 'AppMain',
computed: {
+ // 增加tagviews
+ cachedViews() {
+ return this.$store.state.tagsView.cachedViews
+ },
key() {
return this.$route.path
}
}
+ // mounted() {
+ // console.log(this.cachedViews)
+ // }
}
-
diff --git a/src/layout/components/Navbar.vue b/src/layout/components/Navbar.vue
index 0ca5cf6a09..961884bc97 100644
--- a/src/layout/components/Navbar.vue
+++ b/src/layout/components/Navbar.vue
@@ -1,29 +1,40 @@
-