Browse Source

初始化项目

master
lijuncheng 6 months ago
parent
commit
546d007d1f
  1. 110
      .gitignore
  2. 4
      .hbuilderx/debug.config.json
  3. 24
      .hbuilderx/launch.json
  4. 7
      Dockerfile
  5. 22
      index.html
  6. 53
      nginx.conf
  7. 12051
      package-lock.json
  8. 46
      package.json
  9. 2
      password.txt
  10. 10
      shims-uni.d.ts
  11. 62
      src/App.vue
  12. 67
      src/api/httpRequest3.js
  13. 3834
      src/api/request2.js
  14. 116
      src/common/appUpdate.js
  15. 320
      src/common/array.js
  16. 477
      src/common/balance.js
  17. 1014
      src/common/basic.js
  18. 17
      src/common/calc.js
  19. 42
      src/common/classify.data.js
  20. 147
      src/common/detail.js
  21. 572
      src/common/directory.js
  22. 197
      src/common/label.js
  23. 109
      src/common/record.js
  24. 221
      src/common/style/PDA_style-delete.css
  25. 2772
      src/common/style/new_style.css
  26. 762
      src/common/style/pdabasic.css
  27. 3405
      src/common/style/uni.css
  28. 21
      src/common/utils/auth.js
  29. 54
      src/common/utils/common.js
  30. 9
      src/common/utils/constant.js
  31. 6
      src/common/utils/errorCode.js
  32. 51
      src/common/utils/permission.js
  33. 47
      src/common/utils/ruoyi.js
  34. 37
      src/common/utils/storage.js
  35. 36
      src/components/active-form/active-form.scss
  36. 787
      src/components/active-form/active-form.vue
  37. 760
      src/components/active-form/active-form222.vue
  38. 452
      src/components/active-form/detail.md
  39. 15
      src/components/active-form/mixins.js
  40. 387
      src/components/active-formv1/detail.md
  41. 550
      src/components/active-formv1/index.vue
  42. 704
      src/components/active-formv1/index1.vue
  43. 15
      src/components/active-formv1/mixins.js
  44. 181
      src/components/amap-wx/js/util.js
  45. 1
      src/components/amap-wx/lib/amap-wx.js
  46. 39
      src/components/custom-nomore/custom-nomore.vue
  47. 58
      src/components/custom-refresher/custom-refresher.vue
  48. 1
      src/components/marked/index.js
  49. 1573
      src/components/marked/lib/marked.js
  50. 12542
      src/components/mpvue-citypicker/city-data/area.js
  51. 1503
      src/components/mpvue-citypicker/city-data/city.js
  52. 139
      src/components/mpvue-citypicker/city-data/province.js
  53. 230
      src/components/mpvue-citypicker/mpvueCityPicker.vue
  54. 123
      src/components/mpvue-echarts/src/echarts.vue
  55. 73
      src/components/mpvue-echarts/src/wx-canvas.js
  56. 484
      src/components/mpvue-picker/mpvuePicker.vue
  57. 175
      src/components/mpvueGestureLock/gestureLock.js
  58. 138
      src/components/mpvueGestureLock/index.vue
  59. 157
      src/components/my-paging/my-paging.vue
  60. 38
      src/components/page-foot/page-foot.vue
  61. 16
      src/components/page-head/page-head.vue
  62. 663
      src/components/pullDown/pullDown.vue
  63. 456
      src/components/show-modal/show-modal.vue
  64. 175
      src/components/tab-nvue/mediaList.vue
  65. 5046
      src/components/u-charts/u-charts.js
  66. 24
      src/libs/versionUpdate.js
  67. 76
      src/main.js
  68. 85
      src/manifest.json
  69. 147
      src/mycomponents/balance/balance.vue
  70. 88
      src/mycomponents/balance/balanceDetailPopup.vue
  71. 57
      src/mycomponents/balance/balanceLabel.vue
  72. 98
      src/mycomponents/balance/balanceMove.vue
  73. 54
      src/mycomponents/balance/balanceSelect.vue
  74. 24
      src/mycomponents/balance/batch.vue
  75. 37
      src/mycomponents/balance/bussinessType.vue
  76. 80
      src/mycomponents/balance/handleBalance.vue
  77. 31
      src/mycomponents/balance/location.vue
  78. 62
      src/mycomponents/balance/moveStatus.vue
  79. 34
      src/mycomponents/balance/pack.vue
  80. 59
      src/mycomponents/balance/productionLabel.vue
  81. 58
      src/mycomponents/balance/purchaseLabel.vue
  82. 84
      src/mycomponents/balance/recommendBalance.vue
  83. 31
      src/mycomponents/balance/toLocation.vue
  84. 25
      src/mycomponents/batch/batch.vue
  85. 57
      src/mycomponents/button/requestButton.vue
  86. 31
      src/mycomponents/common/comBlankView.vue
  87. 41
      src/mycomponents/common/comEmptyView.vue
  88. 162
      src/mycomponents/common/comListHint.vue
  89. 108
      src/mycomponents/common/comListItem.vue
  90. 479
      src/mycomponents/common/comMessage.vue
  91. 39
      src/mycomponents/common/comPopup.vue
  92. 120
      src/mycomponents/common/comUploadCamera.vue
  93. 24
      src/mycomponents/container/container.vue
  94. 54
      src/mycomponents/container/containerInfo.vue
  95. 47
      src/mycomponents/container/containerStatus.vue
  96. 68
      src/mycomponents/container/targetContainer.vue
  97. 162
      src/mycomponents/detail/comDetailCard.vue
  98. 161
      src/mycomponents/detail/comJobDetailCard.vue
  99. 151
      src/mycomponents/detail/comRequestDetailCard.vue
  100. 67
      src/mycomponents/detail/detailBalanceInfo.vue

110
.gitignore

@ -1,91 +1,21 @@
# ---> Android
# Built application files
*.apk
*.aar
*.ap_
*.aab
# Files for the ART/Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
out/
# Uncomment the following line in case you need and you don't have the release build type files in your app
# release/
# Gradle files
.gradle/
build/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
# Logs
logs
*.log
# Android Studio Navigation editor temp files
.navigation/
# Android Studio captures folder
captures/
# IntelliJ
*.iml
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
.idea/assetWizardSettings.xml
.idea/dictionaries
.idea/libraries
.idea/jarRepositories.xml
# Android Studio 3 in .gitignore file.
.idea/caches
.idea/modules.xml
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
.idea/navEditor.xml
# Keystore files
# Uncomment the following lines if you do not want to check your keystore files in.
#*.jks
#*.keystore
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
.cxx/
# Google Services (e.g. APIs or Firebase)
# google-services.json
# Freeline
freeline.py
freeline/
freeline_project_description.json
# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md
# Version control
vcs.xml
# lint
lint/intermediates/
lint/generated/
lint/outputs/
lint/tmp/
# lint/reports/
# Android Profiling
*.hprof
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
*.local
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

4
.hbuilderx/debug.config.json

@ -0,0 +1,4 @@
{
"rootPathIndex": 1,
"webRoot": "${projectDir}"
}

24
.hbuilderx/launch.json

@ -0,0 +1,24 @@
{
// launch.json configurations app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
// launchtypelocalremote, localremote
"version" : "0.0",
"configurations" : [
{
"app-plus" : {
"launchtype" : "local"
},
"default" : {
"launchtype" : "local"
},
"type" : "uniCloud"
},
{
"openVueDevtools" : true,
"type" : "uni-app:h5"
},
{
"playground" : "standard",
"type" : "uni-app:app-android"
}
]
}

7
Dockerfile

@ -0,0 +1,7 @@
# 设置基础镜像
FROM win-nginx
WORKDIR /opt/sfms3.0-uniapp
COPY nginx.conf /usr/local/nginx/conf/nginx.conf
# 将dist/build/h5/文件中的内容复制到 /opt/sfms3.0-uniapp 这个目录下面
COPY dist/build/h5/ /opt/sfms3.0-uniapp

22
index.html

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
<!-- 配置H5的 web图标static/logo.png -->
<link rel="icon" href="../../static/logo.png" />
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

53
nginx.conf

@ -0,0 +1,53 @@
user root;
worker_processes 2;
events {
worker_connections 1024;
}
http {
include mime.types;
charset utf-8,gbk;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "$request_time $upstream_response_time"';
proxy_cache_path /opt/nginx_cache/ levels=1:2 keys_zone=my_zone:10m inactive=300s max_size=5g;
access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 600s;
client_max_body_size 200m;
gzip on;
gzip_min_length 10k;
gzip_comp_level 9;
gzip_buffers 4 16k;
gzip_types text/plain application/javascript text/css application/xml text/javascript image/jpeg image/gif image/png;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
upstream sfms3.0 {
server localhost:25310 weight=10 max_fails=3 fail_timeout=10s;
}
server {
listen 25302;
server_name_in_redirect off;
server_name dev.ccwin-in.com;
location /api/ {
proxy_pass http://sfms3.0/;
proxy_next_upstream http_500 http_502 http_503 http_504 error timeout invalid_header;
proxy_set_header X-Forwared-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $http_x_forwarded_for;
}
location / {
proxy_cache my_zone;
proxy_cache_valid 200 304 12h;
proxy_cache_key $host$uri$is_args$args;
try_files $uri $uri/ /index.html;
root /opt/sfms3.0-uniapp;
index index.html index.htm;
}
}
}

12051
package-lock.json

File diff suppressed because it is too large

46
package.json

@ -0,0 +1,46 @@
{
"name": "uni-preset-vue",
"version": "0.0.0",
"scripts": {
"dev:app": "uni -p app",
"dev:app-android": "uni -p app-android",
"dev:app-ios": "uni -p app-ios",
"dev:custom": "uni -p",
"dev": "uni",
"dev:h5:ssr": "uni --ssr",
"dev:mp-weixin": "uni -p mp-weixin",
"build:app": "uni build -p app",
"build:app-android": "uni build -p app-android",
"build:app-ios": "uni build -p app-ios",
"build:custom": "uni build -p",
"test": "uni build",
"build:h5:ssr": "uni build --ssr",
"build:mp-weixin": "uni build -p mp-weixin"
},
"dependencies": {
"@dcloudio/uni-app": "3.0.0-3090920231225001",
"@dcloudio/uni-app-plus": "3.0.0-3090920231225001",
"@dcloudio/uni-components": "3.0.0-3090920231225001",
"@dcloudio/uni-h5": "3.0.0-3090920231225001",
"@dcloudio/uni-mp-weixin": "3.0.0-3090920231225001",
"less": "^4.2.0",
"vue": "^3.2.45",
"vue-i18n": "^9.1.9",
"vuex": "^4.1.0"
},
"devDependencies": {
"@dcloudio/types": "^3.3.2",
"@dcloudio/uni-automator": "3.0.0-3090920231225001",
"@dcloudio/uni-cli-shared": "3.0.0-3090920231225001",
"@dcloudio/uni-stacktracey": "3.0.0-3090920231225001",
"@dcloudio/vite-plugin-uni": "3.0.0-3090920231225001",
"@vue/runtime-core": "^3.2.45",
"axios": "^1.3.4",
"decimal.js": "^10.4.3",
"jwt-decode": "^3.1.2",
"sass": "^1.70.0",
"sass-loader": "^14.1.0",
"vite": "4.0.3",
"vue-clipboard2": "^0.3.3"
}
}

2
password.txt

@ -0,0 +1,2 @@
别名:testalias
密码: wms3.0

10
shims-uni.d.ts

@ -0,0 +1,10 @@
/// <reference types='@dcloudio/types' />
import 'vue'
declare module '@vue/runtime-core' {
type Hooks = App.AppInstance & Page.PageInstance;
interface ComponentCustomOptions extends Hooks {
}
}

62
src/App.vue

@ -0,0 +1,62 @@
<script>
// #ifdef APP-PLUS
import {
appUpdate
} from "@/common/appUpdate.js"
// #endif
export default {
onLaunch: function() {
console.log('App Launch')
// ,
// #ifdef APP-PLUS
// ,
uni.setStorageSync('hasLogin', false)
// plus.navigator.setFullscreen(true);
// // app
// plus.screen.lockOrientation('landscape-primary');
// // app
// plus.screen.lockOrientation('portrait-primary');
appUpdate();
// #endif
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
},
}
</script>
<style lang="scss">
@import "./uni_modules/vk-uview-ui/index.scss";
@import './common/style/new_style.css';
@import './common/style/uni.css';
@import './common/style/pdabasic.css';
@import './uni.scss';
@import './static/scss/index.scss';
@import './static/ali_icon/iconfont.css';
body {
background-color: #EBEEF0;
}
.content {
background-color: #fff
}
page {
// #ifdef APP-PLUS
height: 100vh;
// #endif
// #ifdef H5
// height: calc(100vh-94px);
// #endif
}
</style>

67
src/api/httpRequest3.js

@ -0,0 +1,67 @@
import storage from '../common/utils/storage'
import config from '../static/config.js'
function service(options = {}) {
var token = storage.getStorage(storage.constant.token)
var tenantId = 1
// if(getApp()!=undefined){
// tenantId = getApp().globalData.tenantId
// }
// if(getApp()!=undefined){
// requestUrl = getApp().globalData.request_url
// }
var requestUrl = ""
requestUrl =config.request_url
options.header = {
"content-type": "application/json",
"Authorization": "Bearer "+token,
"dataType":"json",
"tenant-id":tenantId
};
options.timeout = 10000
options.url = requestUrl+options.url
return new Promise((resolve, reject) => {
options.success = (res) => {
if (res ) {
if(res.statusCode == 200){
if(res.data.code==0){
resolve(res.data);
}else {
reject("系统异常:"+res.data.msg)
console.log("系统异常",res.data.msg)
}
}else {
reject("系统异常:"+ res.data.msg)
console.log("系统异常",res.data.msg)
}
} else {
reject("系统异常:"+res.data.msg)
console.log("系统异常",res.data.msg)
}
};
options.fail = (error) => {
var message = error.errMsg
if (message === 'Network Error') {
message = '接口连接异常'
} else if (message.includes('timeout')) {
message = '接口请求超时'
} else if (message.includes('Request failed with status code')) {
message = '接口' + message.substr(message.length - 3) + '异常'
}
reject("系统异常:"+message);
console.log("系统异常",message)
};
uni.request(options);
});
}
export default service;

3834
src/api/request2.js

File diff suppressed because it is too large

116
src/common/appUpdate.js

@ -0,0 +1,116 @@
import {
appCheckUpdate
} from '../api/request2.js';
export function appUpdate() {
let curversion = 0;
plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {
const data = {
action: 'checkVersion',
appid: plus.runtime.appid,
appVersion: plus.runtime.version,
wgtVersion: widgetInfo.version,
versionCode: widgetInfo.versionCode
}
curversion=data.versionCode
appCheckUpdate().then(res => {
console.log("当前版本提示",curversion)
if (res.data) {
if (res.data.versionCode > Number(curversion)) {
var downUrl = res.data.downUrl;
var content = res.data.content;
var version =res.data.version
console.log("新版本提示")
uni.showModal({
title: "发现新版本:("+version+")",
content: content,
confirmText: "更新",
cancelText: "取消",
success: (res) => {
if (res.confirm) {
confirm(downUrl);
console.log('comfirm') //点击确定之后执行的代码
} else {
console.log('cancel') //点击取消之后执行的代码
}
}
})
} else {
uni.showToast({
title:"当前是最新版本"
})
console.log("没有新版本")
}
}
}).catch(error => {
console.log("版本错误", error)
})
})
}
export function confirm(downUrl) {
var downloadApkUrl = downUrl
var dtask = plus.downloader.createDownload(downloadApkUrl, {},
function(d, status) {
// 下载完成
if (status == 200) {
plus.runtime.install(plus.io.convertLocalFileSystemURL(
d.filename), {}, {}, function(error) {
uni.showToast({
title: '安装失败',
duration: 1500
});
})
} else {
uni.showToast({
title: '更新失败',
duration: 1500
});
}
});
try {
dtask.start(); // 开启下载的任务
var prg = 0;
var showLoading = plus.nativeUI.showWaiting(
"正在下载"); //创建一个showWaiting对象
dtask.addEventListener('statechanged', function(
task,
status
) {
// 给下载任务设置一个监听 并根据状态 做操作
switch (task.state) {
case 1:
showLoading.setTitle("正在下载");
break;
case 2:
showLoading.setTitle("已连接到服务器");
break;
case 3:
prg = parseInt(
(parseFloat(task.downloadedSize) /
parseFloat(task.totalSize)) *
100
);
showLoading.setTitle(" 正在下载" + prg + "% ");
break;
case 4:
plus.nativeUI.closeWaiting();
//下载完成
break;
}
});
} catch (err) {
plus.nativeUI.closeWaiting();
uni.showToast({
title: '更新失败-03',
mask: false,
duration: 1500
});
}
}

320
src/common/array.js

@ -0,0 +1,320 @@
// 详情和审批
export function getDetailAndApproveOption() {
let option_detail = [{
text: '详情',
style: {
backgroundColor: '#3C9CFF'
}
},
{
text: '提交\n审批',
style: {
backgroundColor: '#00CC33'
}
},
{
text: '关闭',
style: {
backgroundColor: '#ff0000'
}
}
];
return option_detail;
}
//详情、审批通过、审批驳回
export function getDetailAndApprovePassAndApproveNoOption() {
let option_detail = [{
text: '详情',
style: {
backgroundColor: '#3C9CFF'
}
},
{
text: '审批\n通过',
style: {
backgroundColor: '#00CC33'
}
},
{
text: '审批\n驳回',
style: {
backgroundColor: '#F56C6C'
}
},
{
text: '关闭',
style: {
backgroundColor: '#ff0000'
}
}
];
return option_detail;
}
//详情、处理、审批不通过
export function getDetailAndHandleOption() {
let option_detail = [{
text: '详情',
style: {
backgroundColor: '#3C9CFF'
}
},
{
text: '处理',
style: {
backgroundColor: '#00CC33'
}
},
{
text: '关闭',
style: {
backgroundColor: '#ff0000'
}
}
];
return option_detail;
}
//详情、重新添加、关闭
export function getDetailAndAddAndCloseOption() {
let option_detail = [{
text: '详情',
style: {
backgroundColor: '#3C9CFF'
}
},
{
text: '重新\n添加',
style: {
backgroundColor: '#E6A23C'
}
},
{
text: '关闭',
style: {
backgroundColor: '#F56C6C'
}
}
];
return option_detail;
}
// 采购退货返回侧滑按钮 详情 、编辑、库位、移除
export function getPurchaseReceiptOption(allowModifyQty, allowModifyLocation) {
var option = []
option.push(...getDetailOption())
if (allowModifyQty == "TRUE") {
option.push(...getEditOption())
}
if (allowModifyLocation == "TRUE") {
option.push(...getLocationOption())
}
option.push(...getRemoveOption())
return option;
}
//详情
export function getDetailOption() {
let option_detail = [{
text: '详情',
style: {
backgroundColor: '#3C9CFF'
}
}];
return option_detail;
}
//详情移除(扫描后不允许修改数量)
export function getDetailRemoveOption() {
let option_detail_edit_remove = [{
text: '详情',
style: {
backgroundColor: '#3C9CFF'
}
},
{
text: '移除',
style: {
backgroundColor: '#F56C6C'
}
}
];
return option_detail_edit_remove;
}
export function getRemoveOption() {
let option_detail_remove = [{
text: '移除',
style: {
backgroundColor: '#F56C6C'
}
}];
return option_detail_remove;
}
export function getAddAgainOption() {
let option_detail_remove = [{
text: '详情',
style: {
backgroundColor: '#3C9CFF'
}
}, {
text: '重新\n添加',
style: {
backgroundColor: '#E6A23C'
}
}];
return option_detail_remove;
}
export function getEditOption() {
let option_detail_edit = [{
text: '编辑',
style: {
backgroundColor: '#F1A532'
}
}];
return option_detail_edit;
}
export function getLocationOption() {
let option_detail_location = [{
text: '库位',
style: {
backgroundColor: '#00A3FF'
}
}];
return option_detail_location;
}
//清空
export function getClearOption() {
let option_detail_edit_remove = [{
text: '清空',
style: {
backgroundColor: '#F56C6C'
}
}];
return option_detail_edit_remove;
}
//详情编辑移除
export function getDetailEditRemoveOption() {
let option_detail_edit_remove = [{
text: '详情',
style: {
backgroundColor: '#3C9CFF'
}
},
{
text: '编辑',
style: {
backgroundColor: '#F1A532'
}
},
{
text: '移除',
style: {
backgroundColor: '#F56C6C'
}
}
];
return option_detail_edit_remove;
}
//详情编辑放弃
export function getDetailGiveupOption() {
let option_detail_giveup = [{
text: '详情',
style: {
backgroundColor: '#3C9CFF'
}
},
{
text: '放弃',
style: {
backgroundColor: '#F56C6C'
}
}
];
return option_detail_giveup;
}
//详情编辑移除
export function getEditRemoveOption() {
let option_edit_remove = [{
text: '编辑',
style: {
backgroundColor: '#F1A532'
}
},
{
text: '移除',
style: {
backgroundColor: '#F56C6C'
}
}
];
return option_edit_remove;
}
// 库存状态字典项
export function getInventoryStatusArray() {
let array = [{
text: '待检',
value: "INSP"
}, {
text: '合格',
value: "OK"
}, {
text: '不合格',
value: "NOK"
}, {
text: '隔离',
value: "HOLD"
}, {
text: '报废',
value: "SCRAP"
}]
return array;
}
// 业务类型字典项
export function getBusinessTypeArray() {
let array = [{
text: '供应商发货',
value: "SupplierDeliver"
}, {
text: '采购收货',
value: "PurchaseReceipt"
}, {
text: '采购退货',
value: "PurchaseReturn"
}, {
text: '采购上架',
value: "PurchasePutaway"
}]
return array;
}
export function getLocationTypeArray(data) {
var list = []
if (data == undefined || data == null || data == "") {
return list
}
if (data.indexOf(',') < 0) {
list.push(data)
} else {
var arrayItems = data.split(',')
arrayItems.forEach(res => {
list.push(res)
})
}
return list
}

477
src/common/balance.js

@ -0,0 +1,477 @@
import {
getManagementPrecision,
getPrecisionStrategy,
getBalanceByFilter
} from '@/api/request2.js';
/**
*
获取管理精度查询策略参数
* @param {*}
*
*/
export function getPrecisionStrategyParams(detailSource) {
var itemList = []
detailSource.forEach(item => {
item.subList.forEach(detail => {
if (detail.scaned) {
var filterResult = itemList.filter(res => {
if (res.itemCode == item.itemCode &&
res.locationCode == detail.toLocationCode) {
return res
}
})
//去掉重复元素
if (filterResult.length == 0) {
var result = {
itemCode: item.itemCode,
locationCode: detail.toLocationCode
}
itemList.push(result)
}
}
})
})
return itemList;
}
/**
*
获取管理精度查询策略参数
* @param {*}
*
*/
export function getPrecisionStrategyParamsByLocation(detailSource, toLocationCode) {
var itemList = []
detailSource.forEach(item => {
item.subList.forEach(detail => {
if (detail.scaned) {
detail.toLocationCode = toLocationCode;
var filterResult = itemList.filter(res => {
if (res.itemCode == item.itemCode &&
res.locationCode == detail.toLocationCode) {
return res
}
})
//去掉重复元素
if (filterResult.length == 0) {
var result = {
itemCode: item.itemCode,
locationCode: detail.toLocationCode
}
itemList.push(result)
}
}
})
})
return itemList;
}
/**
* "itemCode": [],
"locationCode":"INSPECT"
管理精度策略
* @param {*}
*
*/
export function getPrecisionStrategyList(itemList, callback) {
// let jsonParem = JSON.stringify(param)
let result = {
list: [],
success: true,
message: ''
};
getPrecisionStrategy(itemList).then(res => {
if (res.data == null) {
result.success = false
result.message = '未查询到管理精度信息'
} else {
result.list = res.data;
}
callback(result);
}).catch(error => {
result.success = false;
result.message = error;
callback(result);
})
}
/**
* "itemCode": [],
"locationCode":"INSPECT"
管理精度策略
* @param {*}
*
*/
export function getManagementPrecisions(itemCodes, locationCode, callback) {
// let jsonParem = JSON.stringify(param)
let result = {
list: [],
success: true,
message: ''
};
var params = {
itemCodes: itemCodes,
locationCode: locationCode
}
getManagementPrecision(params).then(res => {
if (res.data == null) {
result.success = false
result.message = '未查询到管理精度信息'
} else {
result.list = res.data;
}
callback(result);
}).catch(error => {
result.success = false;
result.message = error;
callback(result);
})
}
export function getBalanceByManagementPrecision(label, locationCode, fromInventoryStatuses, callback) {
let result = {
list: [],
success: true,
message: ''
};
let params = {
itemCodes: [label.itemCode],
locationCode: locationCode
};
// let jsonParem = JSON.stringify(param)
getManagementPrecision(params).then(res => {
let managementPrecision = res.data[0].ManagementPrecision;
switch (managementPrecision) {
case 'BY_PACKAGING':
byPacking(label, locationCode, fromInventoryStatuses, res => {
res.managementPrecision = managementPrecision;
callback(res);
});
break;
case 'BY_BATCH':
byBatch(label, locationCode, fromInventoryStatuses, res => {
res.managementPrecision = managementPrecision;
callback(res);
});
break;
case 'BY_QUANTITY':
byQuantity(label, locationCode, fromInventoryStatuses, res => {
res.managementPrecision = managementPrecision;
callback(res);
});
break;
case 'BY_UNIQUEID':
byUniqueId(label, fromInventoryStatuses, res => {
res.managementPrecision = managementPrecision;
callback(res);
});
break;
}
}).catch(error => {
let result = {
success: false,
message: error
};
callback(result);
})
}
/**
* @param {Object} label
* @param {Object} locationCode
* @param {Object} callback
*/
export function byPacking(label, locationCode, fromInventoryStatuses, callback) {
let result = {
success: true,
message: '',
data: {}
};
var filters = []
filters.push({
column: "packingNumber",
action: "==",
value: label.packingNumber
})
filters.push({
column: "itemCode",
action: "==",
value: label.itemCode
})
filters.push({
column: "batch",
action: "==",
value: label.batch
})
filters.push({
column: "locationCode",
action: "==",
value: locationCode
})
if (fromInventoryStatuses != null && fromInventoryStatuses != "") {
filters.push({
column: "inventoryStatus",
action: "in",
value: fromInventoryStatuses
})
}
var params = {
filters: filters,
pageNo: 1,
pageSize: 100,
}
getBalanceByFilter(params).then(res => {
if (res.data == null) {
result.success = false;
result.message =
"按包装管理查询、未查询到物料号[" + label.itemCode + "]" +
"到箱码[" + label.packingNumber + "]" +
"批次[" + label.batch + "]" +
"库位[" + label.locationCode + "]的信息"
} else {
result.success = true;
result.data = res.data;
}
callback(result)
}).catch(err => {
result.success = false;
result.data = null;
result.message = err;
callback(result)
})
}
/**
* @param {Object} label
* @param {Object} locationCode
* @param {Object} callback
*/
export function byBatch(label, locationCode, fromInventoryStatuses, callback) {
var filters = []
filters.push({
column: "itemCode",
action: "==",
value: label.itemCode
})
filters.push({
column: "batch",
action: "==",
value: label.batch
})
filters.push({
column: "packingNumber",
action: "==",
value: null
})
filters.push({
column: "locationCode",
action: "==",
value: locationCode
})
if (fromInventoryStatuses != null && fromInventoryStatuses != "") {
filters.push({
column: "inventoryStatus",
action: "in",
value: fromInventoryStatuses
})
}
var params = {
filters: filters,
pageNo: 1,
pageSize: 100,
}
let result = {
success: true,
message: '',
data: {}
};
getBalanceByFilter(params).then(res => {
if (res.data == null) {
result.success = false;
result.message =
"按批次管理查询、未查询到物料号[" + label.itemCode + "]" +
"批次[" + label.batch + "]" +
"库位[" + label.locationCode + "]的信息"
} else {
result.success = true;
result.data = res.data;
}
callback(result)
}).catch(err => {
result.success = false;
result.data = null;
result.message = err.message;
callback(result)
})
}
/**
* @param {Object} label
* @param {Object} locationCode
* @param {Object} callback
*/
export function byQuantity(label, locationCode, fromInventoryStatuses, callback) {
let result = {
success: true,
message: '',
data: {}
};
var filters = []
filters.push({
column: "itemCode",
action: "==",
value: label.itemCode
})
filters.push({
column: "packingNumber",
action: "==",
value: null
})
filters.push({
column: "batch",
action: "==",
value: null
})
filters.push({
column: "locationCode",
action: "==",
value: locationCode
})
if (fromInventoryStatuses != null && fromInventoryStatuses != "") {
filters.push({
column: "inventoryStatus",
action: "in",
value: fromInventoryStatuses
})
}
var params = {
filters: filters,
pageNo: 1,
pageSize: 100,
}
getBalanceByFilter(params).then(res => {
if (res.data == null) {
result.success = false;
result.message =
"按数量管理查询、未查询到物料号[" + label.itemCode + "]" +
"库位[" + label.locationCode + "]的信息"
} else {
result.success = true;
result.data = res.data;
}
callback(result)
}).catch(err => {
result.success = false;
result.data = null;
result.message = err.message;
callback(result)
})
}
/**
* @param {Object} label
* @param {Object} locationCode
* @param {Object} callback
*/
export function byUniqueId(label, locationCode, fromInventoryStatuses, callback) {
let param = {
packingNumber: label.packingNumber
};
let result = {
success: true,
message: '',
data: {}
};
var filters = []
filters.push({
column: "packingNumber",
action: "==",
value: label.packingNumber
})
if (fromInventoryStatuses != null && fromInventoryStatuses != "") {
filters.push({
column: "inventoryStatus",
action: "in",
value: fromInventoryStatuses
})
}
var params = {
filters: filters,
pageNo: 1,
pageSize: 100,
}
getBalanceByFilter(params).then(res => {
if (res.data == null) {
result.success = false;
result.message =
"按唯一码管理查询、未查询到箱码[" + label.packingNumber + "]" +
"的信息"
} else {
result.success = true;
result.data = res.data;
}
callback(result)
}).catch(err => {
result.success = false;
result.data = null;
result.message = err.message;
callback(result)
})
}
/**
* 查询指定库位下的库存
* @param {*} param
* @param {*} callback
*/
export function balanceByLocation(locationCode, callback) {
let result = {
success: true,
message: '',
data: {}
};
var filters = []
filters.push({
column: "locationCode",
action: "==",
value: locationCode
})
var params = {
filters: filters,
pageNo: 1,
pageSize: 100,
}
getBalanceByFilter(params).then(res => {
if (res.data == null) {
result.success = false;
result.message =
"按唯一码管理查询、未查询到库位[" + label.locationCode + "]" +
"的信息"
} else {
result.success = true;
result.data = res.data;
}
callback(result)
}).catch(err => {
result.success = false;
result.data = null;
result.message = err.message;
callback(result)
})
}

1014
src/common/basic.js

File diff suppressed because it is too large

17
src/common/calc.js

@ -0,0 +1,17 @@
/* 解决js计算精度问题 */
import { Decimal } from 'decimal.js';//引入
class Calc {
add(num1,num2) {
return new Decimal(num1).add(new Decimal(num2)).toNumber()
}
sub(num1,num2) {
return new Decimal(num1).sub(new Decimal(num2)).toNumber()
}
mul(num1,num2) {
return new Decimal(num1).mul(new Decimal(num2)).toNumber()
}
div(num1,num2) {
return new Decimal(num1).div(new Decimal(num2)).toNumber()
}
}
export const calc = new Calc();

42
src/common/classify.data.js

@ -0,0 +1,42 @@
export default [{
"name": "泡沫",
"children": [{
"name": "泡沫点检",
"icon": "/menu_search_lj.svg",
"path": "/pages/foam/check",
"index": 1,
},
{
"name": "原料投入(泡沫)",
"icon": "/menu_search_lj.svg",
"path": "/pages/plastics/input",
"index": 2,
}
]
},
{
"name": "注塑",
"children": [{
"name": "注塑点检",
"icon": "/menu_search_lj.svg",
"path": "/pages/plastics/check",
"index": 1,
},
{
"name": "原料投入(注塑)",
"icon": "/menu_search_lj.svg",
"path": "/pages/plastics/input",
"index": 2,
},
]
}
]

147
src/common/detail.js

@ -0,0 +1,147 @@
import {
calc
} from '@/common/calc'
import {
Decimal
} from 'decimal.js'; //引入
export function getTreeDataSource(dataList) {
let items = [];
let parentList = dataList.filter(r => r.parentPackingNumber == null || r
.parentPackingNumber == '');
let childList = dataList.filter(r => r.parentPackingNumber != '' && r.parentPackingNumber != null);
parentList.forEach(detail => {
var item = items.find(r =>
r.itemCode == detail.itemCode)
if (item == undefined) {
item = createItemInfo(detail);
let newDetail = createDetailInfo(detail); //
item.subList.push(newDetail);
items.push(item)
} else {
item.qty = calc.add(item.qty, detail.qty)
let newDetail = createDetailInfo(detail); //
item.subList.push(newDetail);
}
})
if (childList.length > 0) {
items.forEach(r =>
r.subList.forEach(s => {
s.packList = childList.filter(c => c.parentPackingNumber == s.packingNumber)
s.packList.forEach(pac=>{
pac.scaned=false;
})
})
)
}
return items;
}
export function getDataSource(subList) {
let items = [];
subList.forEach(detail => {
var item = items.find(r =>
r.itemCode == detail.itemCode)
if (item == undefined) {
item = createItemInfo(detail);
let newDetail = createDetailInfo(detail); //
item.subList.push(newDetail);
items.push(item)
} else {
item.qty = calc.add(item.qty, detail.qty)
let newDetail = createDetailInfo(detail); //
item.subList.push(newDetail);
}
})
return items;
}
export function createItemInfo(detail) {
let item = {
itemCode: detail.itemCode,
itemName: detail.itemName,
packQty: Number(detail.packQty) || undefined,
packUnit: detail.packUnit,
qty: Number(detail.qty),
handleQty: 0,
uom: detail.uom,
subList: []
}
return item;
}
export function createDetailInfo(data) {
data.scaned = false;
let detail = data;
detail.packList = [];
return detail;
}
//根据明细创建记录
export function createRecordInfo(detail, balance) {
var record = {}
// let record = JSON.parse(JSON.stringify(detail));
//克隆对象,深度克隆,防止双向绑定同一个变量
Object.assign(record, detail)
detail.scaned = true;
detail.balance = balance;
detail.recommendInventoryStatus = detail.inventoryStatus;
detail.inventoryStatus = balance.inventoryStatus;
record.qty = Number(balance.qty);
return record;
}
//计算实际数量
export function calcHandleQty(detailSource) {
for (let item of detailSource) {
item.handleQty = new Decimal(0).toNumber();
item.qty = new Decimal(0).toNumber();
for (let detail of item.subList) {
if (detail != undefined && detail.scaned) {
item.handleQty = calc.add(item.handleQty, detail.handleQty);
item.qty = calc.add(item.qty, detail.qty);
}
}
}
}
export function calcTreeHandleQty(detailSource) {
for (let item of detailSource) {
item.handleQty = new Decimal(0).toNumber();
for (let detail of item.subList) {
if (detail != undefined && detail.scaned) {
if(detail.packList.length>0){
detail.handleQty = new Decimal(0).toNumber();
for (let pack of detail.packList){
if(pack!=undefined&&pack.scaned){
detail.handleQty = calc.add(detail.handleQty, pack.handleQty);
}
}
}
item.handleQty = calc.add(item.handleQty, detail.handleQty);
}
}
}
}
export function getScanCount(subList) {
let items = subList.filter(r => {
if (r.scaned) {
return r;
}
})
let scanCount = items != null ? items.length : 0;
return scanCount;
}

572
src/common/directory.js

@ -0,0 +1,572 @@
let jobStatusList = [];
let itemStatusList = [];
let itemTypeList =[];
let locationTypeList = [];
let uomList = [];
let inventoryStatusList = [];
let containerTypeList = [];
let packUnitList = [];
let packUnitInfoList = [];
let requestStatusList = [];
let unplannedReceiptReasonList = [];
let unplannedIssueReasonList = [];
let unplannedIissueReason = [];
let scrapReasonList = [];
let inspectFailedReasonList = [];
let inspectResultList = [];
let nextActionList = [];
let inspectTypeList = [];
let sampleMethodList = [];
let transferModeList = [];
let countStageList = [];
let locationAreaTypeList = [];
// 获取业务类型字典项
export function getBusinessTypeDesc(type) {
if (type == "SupplierDeliver") {
return "供应商发货"
} else if (type = "PurchaseReceipt") {
return "采购收货";
} else if (type = "PurchaseReturn") {
return "采购退货";
} else if (type = "PurchasePutaway") {
return "采购上架";
}
}
//获取字典信息
export function clearCacheData() {
jobStatusList = [];
itemStatusList = [];
itemTypeList =[];
locationTypeList = [];
uomList = [];
inventoryStatusList = [];
containerTypeList = [];
packUnitList = [];
packUnitInfoList = [];
requestStatusList = [];
unplannedReceiptReasonList = [];
unplannedIssueReasonList = [];
unplannedIissueReason = [];
scrapReasonList = [];
inspectFailedReasonList = [];
inspectResultList = [];
nextActionList = [];
inspectTypeList = [];
sampleMethodList = [];
transferModeList = [];
countStageList = [];
locationAreaTypeList=[]
}
//获取字典信息
export function getDirectoryInfo(type) {
var result = [];
var list = uni.getStorageSync("dictionary")
if (list != undefined && list.length > 0) {
for (let item of list) {
if (item.type == type) {
result = item.subList
break;
}
}
}
return result
}
//将字典项转为数组
export function getDirectoryItemArray(data) {
var array = []
if (data == undefined || data == null || data == "") {
return array
}
if (data.indexOf(',') < 0) {
array.push(data)
} else {
var arrayItems = data.split(',')
arrayItems.forEach(res => {
array.push(res)
})
}
return array
}
//查询字典项是否在列表中
export function checkDirectoryItemExist(list, type) {
let exist = false;
if (list == null || list.length == 0) {
exist = true;
} else {
var temp = list.filter(res => {
if (res == type) {
return res
}
})
if (temp != undefined && temp.length > 0) {
exist = true
}
}
return exist
}
//获取任务状态
export function getJobStateInfo(value) {
var resultInfo = "";
if (jobStatusList.length == 0) {
jobStatusList = getDirectoryInfo("job_status")
}
if (jobStatusList.length > 0) {
for (let item of jobStatusList) {
if (item.value == value) {
resultInfo = item
break;
}
}
}
return resultInfo
}
//获取任务状态样式
export function getJobStateStyle(value) {
let item = getJobStateInfo(value);
if (item == null || item == '') {
return 'other'
} else {
if (item.remark == '') {
return 'other'
} else {
return item.remark;
}
}
}
//获取库区描述(多个库区)
export function getListLocationAreaTypeDesc(list) {
let desc = '';
list.forEach(res => {
desc += getLocationAreaTypeInfo(res).label + ","
})
desc = desc.slice(0, -1);
return desc;
}
//获取库位描述(多个库位)
export function getListLocationTypeDesc(list) {
let desc = '';
list.forEach(res => {
desc += getLocationTypeInfo(res).label + ","
})
desc = desc.slice(0, -1);
return desc;
}
//获取物品状态(多个状态)
export function getListItemStateDesc(list) {
let desc = '';
list.forEach(res => {
desc += getItemStateInfo(res).label + ","
})
desc = desc.slice(0, -1);
return desc;
}
//获取物品类型(多个)
export function getListItemTypeDesc(list) {
let desc = '';
list.forEach(res => {
desc += getItemTypeInfo(res).label + ","
})
desc = desc.slice(0, -1);
return desc;
}
//获取物品类型
export function getItemTypeInfo(value) {
var resultInfo = "";
if (itemTypeList.length == 0) {
itemTypeList = getDirectoryInfo("item_type")
}
if (itemTypeList.length > 0) {
for (let item of itemTypeList) {
if (item.value == value) {
resultInfo = item
break;
}
}
}
return resultInfo
}
//获取物品状态
export function getItemStateInfo(value) {
var resultInfo = "";
if (itemStatusList.length == 0) {
itemStatusList = getDirectoryInfo("item_status")
}
if (itemStatusList.length > 0) {
for (let item of itemStatusList) {
if (item.value == value) {
resultInfo = item
break;
}
}
}
return resultInfo
}
//获取库区类型
export function getLocationAreaTypeInfo(value) {
var resultInfo = "";
if (locationAreaTypeList.length == 0) {
locationAreaTypeList = getDirectoryInfo("area_type")
}
if (locationAreaTypeList.length > 0) {
for (let item of locationAreaTypeList) {
if (item.value == value) {
resultInfo = item
break;
}
}
}
return resultInfo
}
//获取库位类型
export function getLocationTypeInfo(value) {
var resultInfo = "";
if (locationTypeList.length == 0) {
locationTypeList = getDirectoryInfo("location_type")
}
if (locationTypeList.length > 0) {
for (let item of locationTypeList) {
if (item.value == value) {
resultInfo = item
break;
}
}
}
return resultInfo
}
//获取库区类型名称
export function getLocationAreaTypeName(value) {
let location = getLocationAreaTypeInfo(value);
return location == '' ? value : location.label;
}
//获取库位类型名称
export function getLocationTypeName(value) {
let location = getLocationTypeInfo(value);
return location == '' ? value : location.label;
}
//获取库位类型名称
export function getLocationTypeNameList(lst) {
let desc = '';
lst.forEach(res => {
desc += getLocationTypeInfo(res).label + ","
})
desc = desc.slice(0, -1);
return desc;
}
//获取计量单位
export function getUomInfo(value) {
var resultInfo = "";
if (uomList.length == 0) {
uomList = getDirectoryInfo("uom")
}
if (uomList.length > 0) {
for (let item of uomList) {
if (item.value == value) {
resultInfo = item
break;
}
}
}
return resultInfo
}
//获取包装单位
export function getPackUnitInfo(value) {
var resultInfo = "";
if (packUnitList.length == 0) {
packUnitList = getDirectoryInfo("pack_unit")
}
if (packUnitList.length > 0) {
for (let item of packUnitList) {
if (item.value == value) {
resultInfo = item
break;
}
}
}
return resultInfo
}
//获取申请状态
export function getRequestStateInfo(value) {
var resultInfo = "";
if (requestStatusList.length == 0) {
requestStatusList = getDirectoryInfo("request_status")
}
if (requestStatusList.length > 0) {
for (let item of requestStatusList) {
if (item.value == value) {
resultInfo = item
break;
}
}
}
return resultInfo
}
//获取库存状态
export function getInventoryStatusInfo(value) {
var resultInfo = "";
if (inventoryStatusList.length == 0) {
inventoryStatusList = getDirectoryInfo("inventory_status")
}
if (inventoryStatusList.length > 0) {
for (let item of inventoryStatusList) {
if (item.value == value) {
resultInfo = item
break;
}
}
}
return resultInfo
}
//获取库存样式
export function getInventoryStatusStyle(value) {
let item = getInventoryStatusInfo(value);
if (item == null || item == '') {
return 'other'
} else {
if (item.remark == '') {
return 'other'
} else {
return item.remark;
}
}
}
//获取库存样式
export function getInventoryStatusName(value) {
let item = getInventoryStatusInfo(value);
if (item == null || item == '') {
return value
} else {
if (item.label == '') {
return value
} else {
return item.label;
}
}
}
//获取状态描述 list
export function getInventoryStatusDesc(lst) {
let desc = '';
lst.forEach(res => {
desc += getInventoryStatusInfo(res).label + ","
})
desc = desc.slice(0, -1);
return desc;
}
//获取器具状态
export function getContainerStatusInfo(value) {
var resultInfo = "";
if (containerTypeList.length == 0) {
containerTypeList = getDirectoryInfo("container_type")
}
if (containerTypeList.length > 0) {
for (let item of containerTypeList) {
if (item.value == value) {
resultInfo = item
break;
}
}
}
return resultInfo
}
//获取计划外入库原因
export function getUnPlannedReceiptReasonList(value) {
if (unplannedReceiptReasonList.length == 0) {
unplannedReceiptReasonList = getDirectoryInfo("unplanned_receipt_reason")
}
unplannedReceiptReasonList.forEach(res => {
res.text = res.label;
res.value = res.value
})
return unplannedReceiptReasonList
}
//获取计划外出库原因
export function getUnPlannedIssuseReasonList(value) {
if (unplannedIssueReasonList.length == 0) {
unplannedIssueReasonList = getDirectoryInfo("unplanned_issue_reason")
}
unplannedIssueReasonList.forEach(res => {
res.text = res.label;
res.value = res.value
})
return unplannedIssueReasonList
}
//获取报废出库原因
export function getScarpReasonList(value) {
if (scrapReasonList.length == 0) {
scrapReasonList = getDirectoryInfo("scrap_reason")
}
scrapReasonList.forEach(res => {
res.text = res.label;
res.value = res.value
})
return scrapReasonList
}
//获取检验失败原因
export function getInspectFailedReasonList(value) {
if (inspectFailedReasonList.length == 0) {
inspectFailedReasonList = getDirectoryInfo("inspect_failed_reason")
}
inspectFailedReasonList.forEach(res => {
res.text = res.label;
res.value = res.value
})
return inspectFailedReasonList
}
//获取检验结果
export function getInspectResultList(value) {
if (inspectResultList.length == 0) {
inspectResultList = getDirectoryInfo("inspect_result")
}
inspectResultList.forEach(res => {
res.text = res.label;
res.value = res.value
})
return inspectResultList
}
//获取下一步动作
export function getNextActionList(value) {
if (nextActionList.length == 0) {
nextActionList = getDirectoryInfo("next_action")
}
nextActionList.forEach(res => {
res.text = res.label;
res.value = res.value
})
return nextActionList
}
//获取检验类型
export function getInspectType(value) {
var resultInfo = "";
if (inspectTypeList.length == 0) {
inspectTypeList = getDirectoryInfo("inspect_type")
}
if (inspectTypeList.length > 0) {
for (let item of inspectTypeList) {
if (item.value == value) {
resultInfo = item.label
break;
}
}
}
return resultInfo
}
//获取抽检方式
export function getSampleMethod(value) {
var resultInfo = "";
if (sampleMethodList.length == 0) {
sampleMethodList = getDirectoryInfo("sample_method")
}
if (sampleMethodList.length > 0) {
for (let item of sampleMethodList) {
if (item.value == value) {
resultInfo = item.label
break;
}
}
}
return resultInfo
}
//获取运输方式
export function getTransferModeName(value) {
var resultInfo = "";
if (transferModeList.length == 0) {
transferModeList = getDirectoryInfo("transfer_mode")
}
if (transferModeList.length > 0) {
for (let item of transferModeList) {
if (item.value == value) {
resultInfo = item.label
break;
}
}
}
return resultInfo
}
//获取盘点阶段名称
export function getCountStageName(value) {
var resultInfo = "";
if (countStageList.length == 0) {
countStageList = getDirectoryInfo("count_stage")
}
if (countStageList.length > 0) {
for (let item of countStageList) {
if (item.value == value) {
resultInfo = item.label
break;
}
}
}
return resultInfo
}
//获取包装规格
export function getPackUnitName(value) {
var resultInfo = "";
if (packUnitInfoList.length == 0) {
packUnitInfoList = uni.getStorageSync('packunit');
}
if (packUnitInfoList.length > 0) {
for (let item of packUnitInfoList) {
if (item.code == value) {
resultInfo = item.name
break;
}
}
}
return resultInfo
}
locationAreaTypeList

197
src/common/label.js

@ -0,0 +1,197 @@
let labelDic = [];
import {
getLabelByHeader,
getPackageListByNumber
} from '../api/request2.js';
import {
checkDirectoryItemExist,
getDirectoryItemArray
} from '../common/directory.js';
export function getLabelInfo(scanMsg,headerType, callBack) {
console.log('扫描信息:', scanMsg);
if (scanMsg.length == 0) {
return null
}
let items = scanMsg.split(';');
let header = items[0];
let version = items[1];
if ((header != undefined) && (version!=undefined)) {
var hearList =getDirectoryItemArray(headerType)
if(!checkDirectoryItemExist(hearList,header)){
let labelResult = {
label: {
labelType: "",
barType: '',
code:""
},
package: null,
success: false,
message: '请输入'+headerType+"开始的标签",
}
callBack(labelResult);
return;
}
//解析扫描的是一维码还是二维码
let type = header.substring(header.length - 1, header.length);
if (type == 'Q') //qrcode
{
getQRCodeInfo(header, version, scanMsg, callBack);
} else if (type == 'B') //barcode
{
getBarCodeInfo(header, version, items[2], callBack);
} else { //直接输入文本
getBarCodeInfo('text', 'V1.0', scanMsg, callBack);
}
}else {
getBarCodeInfo('text', 'V1.0', scanMsg, callBack);
// let labelResult = {
// label: {
// labelType: "",
// barType: '',
// code:""
// },
// package: null,
// success: false,
// message: '标签格式不正确',
// }
// callBack(labelResult);
}
}
export function getQRCodeInfo(header, version, scanMsg, callBack) {
//获取包装信息
let labelItem = labelDic.find(r => r.header == header && r.version == version);
if (labelItem == undefined) {
let labelResult = {
label: {
barType: 'QRCode',
},
package: {},
success: true,
message: ''
}
getLabelByHeader(header, version).then(res => {
if (res.data==null) {
labelResult.success = false;
labelResult.message = '未查找到标签头为[' + header + ']的标签类型';
callBack(labelResult);
} else {
let newItem = {
header: header,
version: version,
label: res.data,
};
labelDic.push(newItem);
getLabelItems(newItem, scanMsg, callBack);
}
}).catch(err => {
labelResult.success = false;
labelResult.message = err;
callBack(err);
})
} else {
getLabelItems(labelItem, scanMsg, callBack);
}
}
export function getLabelItems(labelItem, scanMsg, callBack) {
let labelResult = analysisQRCodeLabel(labelItem, scanMsg);
if (labelResult.label.labelType == 'PurchaseLabel' || labelResult.label.labelType == 'MakeLabel') {
//查询包装信息
let packingNumber = labelResult.label.packingNumber
if (packingNumber != undefined) {
getPackageListByNumber(packingNumber).then(pack => {
if (pack.data.reqPackage) {
labelResult.package = pack.data.reqPackage;
labelResult.package.subList = pack.data.subList;
console.log('包装信息', JSON.stringify(labelResult.package))
} else {
labelResult.success = false;
labelResult.message = '包装号[' + packingNumber + ']没有包装信息';
}
callBack(labelResult);
}).catch(err => {
labelResult.success = false;
labelResult.message = err;
callBack(labelResult);
})
} else {
labelResult.success = false;
labelResult.message = '在条码中未解析到箱码';
callBack(labelResult);
}
} else {
callBack(labelResult);
}
}
export function analysisQRCodeLabel(labelItem, scanMsg) {
let labelResult = {
label: {
labelType: labelItem.label.labelType,
barType: 'QRCode',
},
package: {},
success: true,
message: ''
}
let separators = labelItem.label.separators;
if (separators == undefined || separators == null) {
labelResult.message = "未读取到分隔符";
} else {
if (scanMsg.indexOf(separators) < 0) {
labelResult.success = false;
labelResult.message = "标签格式不正确";
} else {
try {
let scanItems = scanMsg.split(separators);
if (scanItems.length > 0) {
scanItems.forEach((item, index) => {
let type = item.substring(0, 1);
let value = item.substring(1, item.length);
if (type == 'H') {
labelResult.label.header = item;
} else if (type == 'V') {
labelResult.label.version = item;
} else {
let barcode = labelItem.label.subList.find(code => code.prefixChar.toUpperCase() ==
type
.toUpperCase());
if (barcode != undefined) {
labelResult.label[barcode.code] = value;
}
}
})
}
} catch (e) {
labelResult.message = e.message;
}
}
}
// console.log('标签', labelResult.label)
return labelResult;
}
export function getBarCodeInfo(header, version, value, callBack) {
let labelResult = {
label: {
labelType: header,
barType: 'BarCode',
code:value
},
package: null,
success: true,
message: '',
}
callBack(labelResult);
}

109
src/common/record.js

@ -0,0 +1,109 @@
import {
getBusinesstypeByCode
} from '@/api/request2.js';
import {
getDirectoryItemArray,
} from '@/common/directory.js';
import { calc } from '@/common/calc'
import { Decimal } from 'decimal.js';//引入
import {
deepCopyData
} from '@/common/basic.js';
export function createItemInfo(balance, pack) {
let item = {
itemCode: pack.itemCode,
itemName: pack.itemName,
packQty: pack.packQty,
packUnit: pack.packUnit,
qty: new Decimal(balance.qty).toNumber(),
handleQty:new Decimal(0).toNumber(),
uom: pack.uom,
subList: []
}
return item;
}
export function createDetailInfo(balance, pack) {
balance.scaned = true;
// data.toInventoryStatus = this.toInventoryStatus == "" ? data.inventoryStatus : this.toInventoryStatus;
// data.inventoryStatus = data.inventoryStatus;
let detail = deepCopyData(balance);
detail.balanceQty = new Decimal(detail.qty).toNumber()
detail.qty = new Decimal(detail.qty).toNumber();
detail.packQty = new Decimal(pack.packQty).toNumber()
detail.packUnit = pack.packUnit
detail.handleQty = new Decimal(detail.qty).toNumber() ;
detail.package = pack;
return detail;
}
//计算实际数量
export function calcHandleQty(detailSource) {
for (let item of detailSource) {
item.handleQty = new Decimal(0).toNumber();
item.qty = new Decimal(0).toNumber();
for (let detail of item.subList) {
if(detail!=undefined){
if(detail.scaned){
item.handleQty = calc.add(item.handleQty,detail.handleQty);
}
item.qty = calc.add(item.qty,detail.qty);
}
}
}
}
export function calcTreeHandleQty(detailSource) {
for (let item of detailSource) {
item.handleQty = new Decimal(0).toNumber();
for (let detail of item.subList) {
if (detail != undefined && detail.scaned) {
detail.handleQty = new Decimal(0).toNumber();
for (let pack of detail.packList){
if(pack!=undefined&&pack.scaned){
detail.handleQty = calc.add(detail.handleQty, pack.handleQty);
}
}
item.handleQty = calc.add(item.handleQty, detail.handleQty);
}
}
}
}
export function getBusinessType(typeCode, callback) {
let result = {
success: true,
businessType: '',
fromLocationAreaTypeList:'',
toLocationAreaTypeList:'',
itemCodeTypeList:"",
useOnTheWay:"FALSE",
fromInventoryStatuses: '',
toInventoryStatuses: '',
message: ''
};
getBusinesstypeByCode(typeCode).then(res => {
if (res.data.total > 0) {
result.businessType = res.data.list[0];
result.fromLocationAreaTypeList = getDirectoryItemArray(res.data.list[0].outAreaTypes) ;
result.toLocationAreaTypeList = getDirectoryItemArray(res.data.list[0].inAreaTypes) ;
result.itemCodeTypeList = getDirectoryItemArray(res.data.list[0].itemTypes)
result.fromInventoryStatuses = res.data.list[0].outInventoryStatuses;
result.toInventoryStatuses = res.data.list[0].inInventoryStatuses;
result.useOnTheWay =res.data.list[0].useOnTheWay
callback(result)
} else {
result.success = false;
result.message = '业务类型[' + typeCode + ']获取失败';
callback(result)
}
}).catch(error => {
result.success = false;
result.message = error;
callback(result)
})
}

221
src/common/style/PDA_style-delete.css

@ -0,0 +1,221 @@
@media screen and (min-width:400px) {
uni-app, uni-page-head{
height: 60px;
}
uni-page-head .uni-page-head{
height: 60px !important;
}
uni-page-head[uni-page-head-type=default]~uni-page-wrapper{
height: calc(100% - 70px) !important;
}
uni-page-head .uni-page-head__title{
font-size: 1.125rem !important;
line-height: 40px !important;
font-weight: normal !important;
}
uni-page-head .uni-btn-icon{
font-size: 1.725rem !important;
}
.font_xs{
font-size: 0.825rem !important;
}
.font_xl{
font-size: 1.325rem !important;
}
.mini-type-style{
font-size: 0.8rem !important;
}
.cen_card .label_box .label_info uni-text{
line-height: 1.725 !important;
/* font-size: 1rem !important; */
color: #333;
}
.cen_card .label_box .label_info{
background-color: #eee !important;
}
.popup_box .detail-list{
box-shadow: none !important;
}
.detail-list,.device-detail{
box-shadow: 0 0 10px rgba(0, 0, 0, 0.15) !important;
}
.list_form .uni-table-tr{
background-color: #f0f0f0 !important;
}
.list_form .uni-table-th{
border-bottom: 1px solid #cfcfcf !important;
}
/* yuanswitch
.require_wrap{
padding-top: 0 !important;
}
.require_wrap .require_cell{
line-height: 1.75 !important;
}
.ljh_box .tit_ljh{
font-size: 1.25rem !important;
}
.cen_card .label_box .label_info {
background-color: #eee !important;
}
.cen_card .label_box .label_info uni-image{
width: 48rpx !important;
height: 48rpx !important;
}
.cen_card .label_box .label_info uni-text{
line-height: 1.5 !important;
font-size: 1rem !important;
color: #333;
}
.ljh_box .tit_ljh .state-style, .top_card .state-style{
font-size: 0.8rem !important;
}
.card_task .ljh_box{
margin-bottom: 0 !important;
}
.task_num uni-image{
width: 56rpx !important;
height: 56rpx !important;
}
.task_num uni-text{
font-size: 1rem !important;
}
.pda_receipt_label .label_order uni-text{
font-size: 1rem;
color: #434556;
}
.pda_receipt_label .icon_normal{
width: 56rpx;
height: 56rpx;
}
.pda_receipt_bot .icon_normal{
width: 56rpx;
height: 56rpx;
float: left;
}
.pda_receipt_bot .text_darkblue{
float: left;
font-size: 1rem;
margin-top: 8rpx;
display: inline-block;
}*/
.top_card .text_lightblue{
font-size: 1rem !important;
}
.top_card .cell_box .cell_info{
margin-bottom: 0;
}
.uni-tab-item-title{
font-size: 1.125rem !important;
}
.cell_box .cell_info uni-view{
font-size: 1rem !important;
color: #101010 !important;
}
.cell_box .cell_info .text_lightblue{
font-size: 0.875rem !important;
color: #6A6E7A !important;
}
.cell_box .cell_info .text_black{
font-size: 1.125rem !important;
}
.scan_float uni-image{
margin-top: 18rpx !important;
}
.scan_float uni-view{
font-size: 0.875rem !important;
letter-spacing: 1px;
}
.new_btn_bot .new_save_btn,.popup_box .pop_title uni-text{
font-size: 1rem !important;
}
.bot_card{
background-color: #eee !important;
}
.bot_card_item uni-text{
font-size: 0.8rem !important;
font-weight: 600;
}
.summary_state .state_point{
font-size: 1rem !important;
}
.summary_item label{
float: left;
}
.summary_item uni-text{
font-size: 1.125rem !important;
font-weight: normal !important;
float: left;
}
/* popup */
.popup_box{
box-sizing: border-box;
}
.popup_box .uni-steps{
width:100%;
overflow-x: hidden;
}
.popup_box .uni-steps__row-line-item{
height: 60rpx !important;
}
.popup_box .uni-steps__row-text-container{
margin-top: 0 !important;
}
.popup_box,.uni-popup .uni-scroll-view-content{
border-top-left-radius:30rpx !important;
border-top-right-radius:30rpx !important;
}
.popup_box .pop_title{
font-size: 1.125rem !important;
letter-spacing: 1px;
}
.popup_box .pop_tab .tab_tit{
font-size: 0.875rem !important;
}
.popup_box .pop_tab .tab_tit_active{
font-size: 1rem !important;
}
.popup_box .pop_tab .tab_info{
min-height: 200rpx !important;
}
.popup_box .pop_tab .tab_info uni-textarea{
height: 200rpx;
}
.popup_box .pop_tab .tab_info uni-button{
font-size: 0.875rem !important;
letter-spacing: 1px;
}
/*底部按钮*/
.new_btn_bot .new_save_btn{
background-color: #E4EAFF !important;
height: 50px;
line-height: 50px;
}
.new_btn_bot .new_clear_btn{
font-size: 1rem !important;
line-height: 50px;
}
.scroll-detail{
padding-bottom: 70px !important;
}
.count_shadow,.device-detail{
box-shadow: 0 0 20rpx rgba(0,0,0,0.2);
}
.list_info {
padding: 0 20rpx 20rpx;
margin-top: 0;
}
.uni-scroll-view-content .creattp_list{
width: 100% !important;
}
.creattp_list .uni-list .list_cell uni-text{
font-weight: bold;
}
.popup_box .scan_scroll{
max-height: 44vh !important;
}
}

2772
src/common/style/new_style.css

File diff suppressed because it is too large

762
src/common/style/pdabasic.css

@ -0,0 +1,762 @@
/*
.pda-list {
padding: 10rpx 10rpx;
box-sizing: border-box;
display: flex;
width: 100%;
flex-direction: row;
}
*/
/* 列表 */
.pda-list {
padding: 0 20rpx;
box-sizing: border-box;
background-color: #FFFFFF;
position: relative;
width: 100%;
display: flex;
flex-direction: column;
border-radius: 16rpx;
margin-bottom: 10rpx;
}
.pda-list:after {
position: absolute;
z-index: 10;
/* right: 0; */
bottom: 0;
left: 0;
height: 1px;
content: '';
-webkit-transform: scaleY(.5);
transform: scaleY(.5);
background-color: #c8c7cc;
}
.pda-list-cell {
position: relative;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #eee;
padding: 10rpx 0;
}
.pda-list-cell:last-child {
border-bottom: 0;
}
.pda-list-cell-left {
white-space: nowrap;
/* padding: 0 10rpx; */
}
.pda-list-cell-db,
.pda-list-cell-right {
flex: 1;
}
.pda-list-cell .pda-list-cell-db .uni-input-input {
font-size: .875rem;
}
.pda-list-cell .uni-easyinput__content-input,
.pda-list-cell .uni-input-placeholder {
height: 2rem;
line-height: 2rem;
}
.pda-list-cell .placeholder {
color: #999 !important;
font-size: 0.875rem;
padding-left: 10rpx;
}
.pda-list-cell .uni-label {
color: #434556;
}
.list_locode .uni-collapse-item__title-box {
font-weight: bold !important;
}
.display-flex {
display: flex;
justify-content: space-between;
align-items: center;
}
.list-body {
/* height: 84rpx; */
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
overflow: hidden;
}
.list-text-top {
width: 100%;
color: #000;
font-weight: bolder;
/* line-height: 36rpx; */
/* font-size: 30rpx; */
}
.list-text-bottom {
/* line-height: 30rpx; */
/* font-size: 26rpx; */
color: #8f8f94;
}
/* 改为detail-content */
/* margin-bottom: 20rpx; */
.device-detail {
padding: 10rpx !important;
margin: 10rpx;
border-radius: 16rpx;
background-color: #fff;
color: #666666;
line-height: 1.5;
overflow: hidden;
}
.list-style {
margin-bottom: 0rpx;
border-radius: 16rpx;
background-color: #FFFFFF;
color: #666666;
line-height: 1.5;
}
.border-font {
color: #000;
font-weight: bolder;
}
.space-between {
-webkit-justify-content: space-between;
justify-content: space-between;
}
.accept-button {
width: 30%;
font-size: 16px;
background-color: #7ac756;
color: #ffffff;
}
.bigsave-button {
width: 80%;
font-size: 16px;
background-color: #007AFF;
color: #ffffff;
}
.save-button {
width: 30%;
font-size: 16px;
background-color: #007AFF;
color: #ffffff;
}
.scroll-detail {
overflow: hidden;
padding-bottom: 60px;
height: 480px;
/* 没有高度不可以回到顶部 */
/* background-color: #ffffff; */
}
.scrollView {
overflow: hidden;
padding-bottom: 50px
}
.scroll-Y {
/* height: 70ux; */
padding-bottom: 50px
}
.bottom1 {
position: fixed;
width: 100%;
/* padding: 10rpx 10rpx; */
left: 0;
/* right: 0; */
bottom: 0;
background-color: #ffffff;
}
.bottom {
position: fixed;
display: flex;
width: 100%;
padding: 10rpx 10rpx;
left: 0;
/* right: 0; */
bottom: 0;
background-color: #ffffff;
}
.pars-num {
/* font-size: 26rpx; */
}
.right-width {
text-align: center;
width: 100rpx;
}
.state-style {
float: left;
margin-top: 10rpx;
/* border-radius: 16rpx;
padding: 0rpx 10rpx; */
/* line-height: 50rpx;
height: 50rpx; */
/* width: 120rpx;
display: flex;
flex-direction: column;
align-items: center; */
/* 垂直居中 */
}
.uni-popup-view {
background-color: #fff;
border-radius: 10px;
}
.uni-popup-button-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
padding: 10px 15px;
}
.uni-popup-button {
flex: 1;
/* // border-radius: 50px;
// color: #666; */
/* font-size: 16px; */
}
/* 任务状态 */
/* 打开 */
.open {
font-size: 28rpx;
background: rgba(95, 203, 148, 0.2);
color: #22AF68;
padding: 10rpx 20rpx 10rpx 20rpx;
border-radius: 10rpx;
}
/* 进行中 */
.pending {
font-size: 28rpx;
background: rgba(236, 156, 0, 0.2);
color: #EC9C00;
padding: 10rpx 20rpx 10rpx 20rpx;
border-radius: 10rpx;
}
/* 完成 */
.completed {
background-color: #E6A23C;
color: #FFFFFF;
border-radius: 10rpx;
}
/* 关闭 */
.close {
background-color: #F56C6C;
color: #FFFFFF;
}
/* 关闭 */
.other {
background-color: #808080;
color: #FFFFFF;
border-radius: 10rpx;
}
/* 其他 */
.unk {
background-color: #ececec;
color: #666;
border-radius: 10rpx;
}
/* 检验任务状态 */
/* 免检 */
.exempt {
background-color: #409EFF;
color: #FFFFFF;
}
/* 全检 */
.full {
background-color: #67C23A;
color: #FFFFFF;
}
/* 抽检 */
.sampling {
background-color: #E6A23C;
color: #FFFFFF;
}
/* 挑检 */
.pick {
background-color: #F56C6C;
color: #FFFFFF;
}
/* 库存状态 */
.uni-link {
background-color: #BD2C00;
color: #BD2C00 !important;
}
.inventory_status_insp {
color: #F9AE3D;
margin-right: 10rpx;
}
.inventory_status_ok {
color: #67C23A;
margin-right: 10rpx;
}
.inventory_status_nok {
color: #FF2424;
margin-right: 10rpx;
}
.inventory_status_hold {
color: #EC9C00;
margin-right: 10rpx;
}
.inventory_status_scarp {
color: #999;
margin-right: 10rpx;
}
.frozen {
color: #FF581D;
margin-right: 10rpx;
}
.pass {
color: #67C23A !important;
}
.unPass {
color: #FF2424 !important;
}
.location_inspect {
background-color: #F6CB61;
color: #FFFFFF;
}
.location_raw {
background-color: #2DA8D8;
color: #FFFFFF;
}
.location_semi {
background-color: #EDAE50;
color: #FFFFFF;
}
.location_fg {
background-color: #078343;
color: #FFFFFF;
}
.location_wip {
background-color: #FC85FE;
color: #FFFFFF;
}
.location_scrap {
background-color: #E30016;
color: #FFFFFF;
}
.location_noc {
background-color: #C31223;
color: #FFFFFF;
}
.location_overflow {
background-color: #7D1EDC;
color: #FFFFFF;
}
.location_customer {
background-color: #5A7CF3;
color: #FFFFFF;
}
.location_hold {
background-color: #FF8C00;
color: #FFFFFF;
}
/* //物料状态
export function getItemTypeStyle(val) {
if (val == 0) return 'active'
else if (val == 1) return 'hold'
else if (val == 2) return 'new'
else if (val == 3) return 'plan'
else if (val == 4) return 'disable'
else return 'other'
}
*/
/* 物料状态 */
.active {
background-color: #5FCB94;
color: #FFFFFF;
}
.hold_item {
background-color: #FF4206;
color: #FFFFFF;
}
.new {
background-color: #E6A23C;
color: #FFFFFF;
}
.plan {
background-color: #2677F9;
color: #FFFFFF;
}
.disable {
background-color: #666;
color: #FFFFFF;
}
/* 任务编号字体 */
.text-number {
color: #000;
font-weight: bolder;
}
/* 物料编号字体 */
.text-itemcode {
/* font-size: 26rpx; */
color: #000;
font-weight: bolder;
}
.text-desc {
color: #8f8f91;
/* font-size: 22rpx; */
}
/* 物料编号字体 */
.text-bolder {
color: #000;
font-weight: bolder;
}
.detail-list {
background-color: #fff;
padding:5rpx 10rpx;
/* margin: 20rpx; */
/* border-radius: 16rpx; */
/* overflow: hidden; */
}
.detail-content {
position: relative;
flex: 1;
/* font-size: 26rpx; */
color: #101010;
}
.example-body {
background-color: #FFFFFF;
}
.result-box {
text-align: center;
padding: 20px 0px;
/* font-size: 16px; */
}
.toptext {
padding-left: 20upx;
line-height: 80upx;
}
.numberstyle {
display: flex;
/* flex-direction: row-reverse; */
border-bottom: 10upx solid #EEEEEE;
width: 200upx;
padding-bottom: 20upx;
}
.input {
height: 20rpx;
padding: 0rpx 8rpx;
line-height: 50rpx;
/* font-size: 25rpx; */
background: #FFF;
border-radius: 4rpx;
flex: 1;
}
.mini-type-style {
vertical-align: middle;
font-size: 0.725rem;
margin-right: 6rpx;
border-radius: 4rpx;
padding: 4rpx 8rpx;
/* width: 80rpx; */
/* height: 46rpx;
min-width: 80rpx;
display: flex;
flex-direction: column; */
}
.text-color {
color: #000;
font-weight: bolder;
}
.tabs {
flex: 1;
flex-direction: column;
overflow: hidden;
/* background-color: #ffffff; */
}
/* .scroll-h {
touch-action: none;
width: 100%;
height: 100rpx;
flex-direction: row;
white-space: nowrap;
justify-content: center;
} */
.line-h {
height: 1rpx;
background-color: #cccccc;
}
.uni-tab-item {
/* #ifndef APP-PLUS */
display: inline-block;
/* #endif */
flex-wrap: nowrap;
padding: 0 30rpx;
}
.uni-tab-item-title {
position: relative;
color: #555;
/* font-size: 24rpx; */
height: 100rpx;
line-height: 100rpx;
flex-wrap: nowrap;
/* #ifndef APP-PLUS */
white-space: nowrap;
/* #endif */
}
.uni-tab-item-title-active {
color: #101010;
font-weight: bold;
}
.uni-tab-item-title-active:after {
left: 50%;
transform: translateX(-50%);
position: absolute;
bottom: -20rpx;
display: inline-block;
content: "";
width: 40rpx;
height: 8rpx;
background-color: #5a7cf3;
border-radius: 5px;
}
/* .blece {
padding: 10upx;
color: #111111;
border-bottom: 2px solid #f5f5f5;
display: flex;
flex-wrap: wrap;
} */
.conbox {
/* padding: 10rpx 0; */
padding-left: 10rpx;
}
.myinput {
display: flex;
box-sizing: border-box;
overflow: hidden;
position: relative;
flex: 1;
justify-content: center;
flex-direction: row;
align-items: center;
height: 88rpx;
padding: 20rpx 0;
/* border-width: 0.5px;
border-style: solid;
border-color: #e5e5e5;
border-radius: 5px;
background-color: rgb(248, 248, 248);
font-size: 18px;*/
font-size: .825rem;
}
.qtyinput {
height: 50px;
padding: 10px 0px;
font-size: 20px;
}
.count-input {
padding: 5rpx 3rpx;
width: 95%;
font-size: 18px;
}
.pda-data-picker {
padding: 5rpx 3rpx;
width: 95%;
font-size: 18px;
}
.inputPlaceholderStyle {
font-size: 16px;
}
.inputfocus {
border-color: #007AFF;
}
.txt-16 {
font-size: 16px;
}
.txt-18 {
font-size: 18px;
}
.txt-20 {
font-size: 20px;
}
.pda-label {
width: 210rpx;
word-wrap: break-word;
word-break: break-all;
text-indent: 20rpx;
font-size: 16px;
}
.fontsize-16 {
font-size: 16px;
}
.fontsize-18 {
font-size: 18px;
}
.fontsize-20 {
font-size: 20px;
}
/deep/ .uni-collapse-item__title-text {
font-size: 16px;
}
/deep/ .input-value {
font-size: 16px;
}
/deep/ .uni-input-input {
font-size: 18px;
}
page {
width: 100%;
height: 100%;
background-color: #fff;
}
.page-wraper {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
/* background-color: #fff; */
}
.page-header {
background-color: #fff;
font-size: 35rpx;
padding: 10rpx 20rpx;
}
.page-header .header_item {
/* padding-left: 10rpx; */
padding: 5rpx 10rpx;
font-size:32rpx ;
}
.page-header .header_job_top {
padding:5rpx 0rpx;
}
.page-main {
flex: 1;
position: relative;
background: #fff;
}
.page-main-scroll {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
.page-main-list {
/* height: 80rpx;
line-height: 80rpx; */
text-align: center;
background: #e0e0e0;
}

3405
src/common/style/uni.css

File diff suppressed because it is too large

21
src/common/utils/auth.js

@ -0,0 +1,21 @@
const AccessTokenKey = 'ACCESS_TOKEN'
const RefreshTokenKey = 'REFRESH_TOKEN'
// ========== Token 相关 ==========
export function getAccessToken() {
return uni.getStorageSync(AccessTokenKey)
}
export function getRefreshToken() {
return uni.getStorageSync(RefreshTokenKey)
}
export function setToken(token) {
uni.setStorageSync(AccessTokenKey, token.accessToken)
uni.setStorageSync(RefreshTokenKey, token.refreshToken)
}
export function removeToken() {
uni.removeStorageSync(AccessTokenKey)
uni.removeStorageSync(RefreshTokenKey)
}

54
src/common/utils/common.js

@ -0,0 +1,54 @@
/**
* 显示消息提示框
* @param content 提示的标题
*/
export function toast(content) {
uni.showToast({
icon: 'none',
title: content
})
}
/**
* 显示模态弹窗
* @param content 提示的标题
*/
export function showConfirm(content) {
return new Promise((resolve, reject) => {
uni.showModal({
title: '提示',
content: content,
cancelText: '取消',
confirmText: '确定',
success: function(res) {
resolve(res)
}
})
})
}
/**
* 参数处理
* @param params 参数
*/
export function tansParams(params) {
let result = ''
for (const propName of Object.keys(params)) {
const value = params[propName]
var part = encodeURIComponent(propName) + "="
if (value !== null && value !== "" && typeof (value) !== "undefined") {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
let params = propName + '[' + key + ']'
var subPart = encodeURIComponent(params) + "="
result += subPart + encodeURIComponent(value[key]) + "&"
}
}
} else {
result += part + encodeURIComponent(value) + "&"
}
}
}
return result
}

9
src/common/utils/constant.js

@ -0,0 +1,9 @@
const constant = {
avatar: 'vuex_avatar',
name: 'vuex_name',
roles: 'vuex_roles',
permissions: 'vuex_permissions',
tenantId:'vuex_tenantId'
}
export default constant

6
src/common/utils/errorCode.js

@ -0,0 +1,6 @@
export default {
'401': '认证失败,无法访问系统资源',
'403': '当前操作没有权限',
'404': '访问资源不存在',
'default': '系统未知错误,请反馈给管理员'
}

51
src/common/utils/permission.js

@ -0,0 +1,51 @@
import store from '@/store'
/**
* 字符权限校验
* @param {Array} value 校验值
* @returns {Boolean}
*/
export function checkPermi(value) {
if (value && value instanceof Array && value.length > 0) {
const permissions = store.getters && store.getters.permissions
const permissionDatas = value
const all_permission = "*:*:*"
const hasPermission = permissions.some(permission => {
return all_permission === permission || permissionDatas.includes(permission)
})
if (!hasPermission) {
return false
}
return true
} else {
console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`)
return false
}
}
/**
* 角色权限校验
* @param {Array} value 校验值
* @returns {Boolean}
*/
export function checkRole(value) {
if (value && value instanceof Array && value.length > 0) {
const roles = store.getters && store.getters.roles
const permissionRoles = value
const super_admin = "admin"
const hasRole = roles.some(role => {
return super_admin === role || permissionRoles.includes(role)
})
if (!hasRole) {
return false
}
return true
} else {
console.error(`need roles! Like checkRole="['admin','editor']"`)
return false
}
}

47
src/common/utils/ruoyi.js

@ -0,0 +1,47 @@
/**
* 通用js方法封装处理
* Copyright (c) 2019 ruoyi
*/
// 日期格式化
export function parseTime(time, pattern) {
if (arguments.length === 0 || !time) {
return null
}
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time)
} else if (typeof time === 'string') {
time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm),'');
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') {
return ['日', '一', '二', '三', '四', '五', '六'][value]
}
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return time_str
}

37
src/common/utils/storage.js

@ -0,0 +1,37 @@
// 获取本地存储对应key
const getStorage = (key)=>{
return uni.getStorageSync( key );
}
// 设置本地存储对应key
const setStorage = (key,value)=>{
return uni.setStorageSync( key,value );
}
// 清除全部本地存储
const clearStorage = ()=>{
uni.clearStorageSync();
}
// 清除指定key本地存储
const removeStorage = ( key )=>{
uni.removeStorageSync( key );
}
const constant = {
id:"id",
token:"token",
avatar: 'avatar',
name: 'name',
roles: 'roles',
permissions: 'permissions'
}
export default {
getStorage,
setStorage,
clearStorage,
removeStorage,
constant
}

36
src/components/active-form/active-form.scss

@ -0,0 +1,36 @@
.active-form {
.u-radio-group--row, .u-checkbox-group--row {
flex-wrap: wrap;
}
.u-radio, .u-checkbox {
margin: 10rpx;
}
}
.flex-row-sb-c {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}
.flex-col--c {
display: flex;
flex-direction: column;
align-items: center;
}
.pr20{
padding-right: 20rpx;
}
.pt30{
padding-top: 30rpx;
}
.p30{
padding: 30rpx;
}
.font26{
font-size: 26rpx;
}

787
src/components/active-form/active-form.vue

@ -0,0 +1,787 @@
<template>
<view class="active-form form-container">
<view class="form-box">
<block v-for="(item, index) in formData" :key="item.id">
<view class="form-item flex-row--c">
<!-- 单行文本框 -->
<view
class="line"
v-if="
item.type === 'text' ||
item.type === 'number' ||
item.type === 'code'
"
>
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view>
<!-- 发送验证码 -->
<view
class="line-right flex-row-sb-c pr20"
v-if="item.type === 'code'"
>
<input
type="text"
class="input"
:disabled="item.disabled"
placeholder-class="plaClass"
:placeholder="item.placeholder"
v-model="form[item.rules.name]"
@input="inputVal(index)"
/>
<view style="width:250rpx">
<u-button
size="mini"
type="primary"
:disabled="item.disabled||isSend"
@click="sendCode(item)"
>
{{ codeFont }}
</u-button>
</view>
</view>
<!-- 普通输入框 -->
<view class="line-right" v-else>
<input
type="text"
class="input"
:disabled="item.disabled"
placeholder-class="plaClass"
:placeholder="item.placeholder"
v-model="form[item.rules.name]"
@input="inputVal(index)"
/>
</view>
</view>
<!-- 下拉选择-->
<template v-else-if="item.type === 'select'">
<view class="line" @click="showSelect(item)">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view>
<view class="line-right pr20">
<view class="input plaClass">
<text>
{{
item.list.find(v => v.value === form[item.rules.name]) && item.list.find(v => v.value === form[item.rules.name]).name || ''
}}
</text>
<text class="input-placeholder" v-if="!form[item.rules.name]">{{
item.placeholder
}}
</text>
</view>
<u-icon name="arrow-down-fill"></u-icon>
</view>
</view>
<u-action-sheet :actions="item.list"
:title="item.title"
safeAreaInsetBottom
round="40"
cancelText="取消"
:show="item.show"
@select="selectConfirm($event,item)"
@close="selectClose(item)"
></u-action-sheet>
</template>
<block v-else-if="item.type === 'datetime'">
<view class="line" @click="showSelect(item)">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view>
<view class="line-right pr20">
<view class="input plaClass">
<text>{{ form[item.rules.name] }}</text>
<text class="input-placeholder" v-if="!form[item.rules.name]">{{
item.placeholder
}}
</text>
</view>
<u-icon name="arrow-down-fill"></u-icon>
</view>
</view>
时间{{item.params}}
<u-picker
:mode="'time'"
v-model="item.show"
:params="item.params"
@confirm="selectTime($event,item)">
</u-picker>
</block>
<!-- 多行文本框 -->
<view class="textarea-box" v-else-if="item.type === 'textarea'">
<view :class="item.rules.verify ? '' : 'p-l14 '">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view>
<view class="line-bottom-textarea">
<!-- placeholder-class="plaClass" -->
<textarea
style="color: #a7a7a7; font-size: 24rpx"
auto-height
:maxlength="-1"
:disabled="item.disabled"
:placeholder="item.placeholder"
v-model="form[item.rules.name]"
@input="inputVal(index)"
>
</textarea>
</view>
</view>
<!-- 上传图片 -->
<view class="img-box pt30 flex-col-l" v-else-if="item.type === 'file'">
<view class="font26" :class="item.rules.verify ? '' : 'p-l14 '">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view>
<view class="img-upload p30">
<u-upload
:fileList="form[item.rules.name]"
:disabled="item.disabled"
:accept="item.accept"
:capture="item.capture"
:maxCount="item.maxCount"
:sizeType="item.sizeType"
:compressed="item.compressed"
:camera="item.camera"
:multiple="item.multiple"
:maxSize="item.maxSize"
:previewImage="item.previewImage"
width="150rpx"
height="150rpx"
@afterRead="afterRead($event,item)"
@delete="deletePic($event,item)"
></u-upload>
</view>
</view>
<!-- 单选框 -->
<view class="line-col" v-else-if="item.type === 'radio'">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
<text
style="
font-size: 20rpx;
color: #9e9e9e;
margin-left: 23rpx;
width: 140rpx;
"
>(单选)
</text>
</view>
<view
class="line-bottom-select"
:style="{ 'padding-left': num ? '60rpx' : '34rpx' }"
>
<u-radio-group
v-model="form[item.rules.name]"
@change="radioChange($event, index)"
placement="row"
>
<u-radio
:size="35"
:icon-size="35"
:label-size="25"
shape="circle"
v-for="(radioItem, radioIndex) in item.list"
:key="radioIndex"
:disabled="radioItem.disabled"
>
{{radioItem.name}}
</u-radio>
</u-radio-group>
</view>
</view>
<!-- 多选框 -->
<view class="line-col" v-else-if="item.type === 'checkbox'">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
<text
style="
font-size: 20rpx;
color: #9e9e9e;
margin-left: 23rpx;
width: 140rpx;
"
>(多选)
</text>
</view>
<view
class="line-bottom-select pr20"
:style="{ 'padding-left': num ? '60rpx' : '34rpx' }"
>
<u-checkbox-group
v-model="form[item.rules.name]"
@change="checkboxGroupChange($event,item)"
>
<u-checkbox
icon-size="25rpx"
label-size="25rpx"
size="30rpx"
v-for="(checkboxItem, checkboxIndex) in item.list"
:key="checkboxIndex"
:label="checkboxItem.label"
:disabled="checkboxItem.disabled"
:name="checkboxItem.value"
>
</u-checkbox>
</u-checkbox-group>
</view>
</view>
<!-- 手机输入框 -->
<view class="line" v-else-if="item.type === 'mobile'">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view>
<view class="line-right pr20">
<input
type="number"
v-model="form[item.rules.name]"
:placeholder="item.placeholder"
@input="inputVal(index)"
class="input"
:disabled="item.disabled"
:maxlength="11"
placeholder-class="plaClass"
/>
<view style="width:200rpx" v-if="item.oneKeyPhone">
<u-button
size="mini"
type="primary"
open-type="getPhoneNumber"
@getphonenumber="getphonenumber"
:disabled="item.disabled"
>一键获取
</u-button>
</view>
</view>
</view>
</view>
</block>
</view>
</view>
</template>
<script>
import mixins from "./mixins";
export default {
name: "activeForm",
mixins: [mixins],
props: {
//
num: {
type: Boolean,
default: false,
},
value: {
type: Object,
default: () => {
return {};
},
},
formData: {
type: Array,
default: () => {
return [];
},
},
//
isEdit: {
type: Boolean,
default: false,
},
//
isDel: {
type: Boolean,
default: false,
},
},
data() {
return {
submitData: "",
selectBox: [],
currentSelectIndex: "",
currentSelectValue: "",
codeFont: "获取验证码",
wait: 60,
isSend: false,
form: {},//form//
};
},
computed: {
// formData: {
// get() {
// // console.log("this.formData", this.value)
// return this.value
// },
// set(nval) {
// this.$emit("input", nval);
// }
// }
},
mounted() {
setTimeout(() => {
this.dataFormat()
})
},
methods: {
//
dataFormat() {
let formDefault = this.extractRules(this.formData)
let formValue = this.value
let form = Object.assign(formDefault, formValue)
console.log("form", form)
this.$set(this, 'form', form)
},
//keyvalue
extractRules(formData) {
const extractedRules = {};
formData.forEach(field => {
const {rules} = field;
if (rules.name) {
extractedRules[rules.name] = rules.value;
}
});
return extractedRules;
},
//
deletePic($event, item) {
item.rules.value.splice($event.index, 1)
this.form[item.rules.name] = item.rules.value
this.$emit('input', this.form)
},
//
afterRead($event, item) {
// mutiple true , file
item.rules.value = item.multiple ? $event.file : [$event.file]
this.form[item.rules.name] = item.rules.value
this.$emit('input', this.form)
},
//select
showSelect(item) {
item.show = true;
this.$emit('input', this.form)
this.$forceUpdate()
},
//input
inputVal(index) {
const data = {
val: this.formData[index].rules.value,
index: index,
};
if (String(data.val) !== "" && String(data.index) !== "") {
this.formData[data.index].rules.value = data.val;
}
this.$emit("input", this.form);
},
//
selectConfirm($event, item) {
item.rules.value = $event.value;
this.form[item.rules.name] = $event.value;
item.show = false
this.$emit("input", this.form);
this.$forceUpdate()
},
selectCalendar($event, item) {
const dateString = $event.reduce((b, n) => (b + `,${n}`))
console.log("selectCalendar", dateString)
// item.rules.label = dateString;
this.form[item.rules.name] = item.rules.value = dateString;
item.show = false
this.$emit("input", this.form);
this.$forceUpdate()
},
selectTime({year, month, day, hour, minute, second}, item) {
let date = ''
if (year) {
date += year + '-'
}
if (month) {
date += month + '-'
}
if (day) {
date += day
}
if (hour) {
date += ' ' + hour
}
if (minute) {
date += ':' + minute
}
if (second) {
date += ':' + second
}
item.rules.value = date
item.rules.label = date;
this.$emit("input", this.form);
},
// value:mode:
selectDateTime($event, item) {
console.log("selectDateTime", item)
const formatValue = $event.mode === 'time' ? this.formatTime(this.getTimestampFromTime($event.value), $event.mode) : this.formatTime($event.value, $event.mode)
// item.rules.label = formatValue
this.form[item.rules.name] = item.rules.value = item.returnTimestamp ? ($event.mode === 'time' ? this.getTimestampFromTime($event.value) : $event.value) : formatValue; //
item.show = false
this.$emit("input", this.form);
this.$forceUpdate()
},
// datetimeyear-month ,datetime
formatTime(timestamp, formatType) {
const date = new Date(timestamp);
if (isNaN(date)) {
return "Invalid Date";
}
let year = date.getFullYear();
let month = String(date.getMonth() + 1).padStart(2, "0");
let day = String(date.getDate()).padStart(2, "0");
let hours = String(date.getHours()).padStart(2, "0");
let minutes = String(date.getMinutes()).padStart(2, "0");
let seconds = String(date.getSeconds()).padStart(2, "0");
switch (formatType) {
case "date":
return `${year}-${month}-${day}`;
case "time":
return `${hours}:${minutes}`; //:${seconds}
case "year-month":
return `${year}-${month}`;
case "datetime":
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
default:
return "Invalid Format Type";
}
},
// "11:00"
getTimestampFromTime(inputTime) {
//
const currentDate = new Date();
//
const [hours, minutes] = inputTime.split(':');
//
const targetDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate(), hours, minutes);
//
const timestamp = targetDate.getTime();
return timestamp;
},
selectClose(item) {
item.show = false;
this.$forceUpdate()
},
//
radioChange($event, index) {
this.$emit("input", this.form);
},
//
checkboxGroupChange($event, item) {
// console.log("$event", $event)
const selectArr = item.list.filter((v => ($event.includes(v.label)))) //
// console.log("selectArr", selectArr)
this.form[item.rules.name] = item.rules.value = selectArr.map(v => (v.value))
this.$emit("input", this.form);
},
//
sendCode(item) {
let setTime = 0;
this.sendCodeCallback(item)
if (!this.isSend) {
this.isSend = true;
setTime = setInterval(() => {
this.wait--;
this.codeFont = this.wait + "重新发送";
if (this.wait === 0) {
clearInterval(setTime);
this.codeFont = "获取验证码";
this.isSend = false;
this.wait = 60;
}
}, 1000);
}
},
//
vervify() {
return new Promise((resolve, reject) => {
this.formData.forEach((item) => {
if (item.rules.verify) {
switch (item.type) {
case "checkbox":
if (this.form[item.rules.name].length === 0) {
uni.showToast({
title: item.rules.errMess || "请选择" + item.label,
duration: 2000,
icon: "none",
});
throw Error(); //
}
break;
case "file":
if (this.form[item.rules.name].length === 0) {
uni.showToast({
title: item.rules.errMess || "请选择" + item.label,
duration: 2000,
icon: "none",
});
throw Error(); //
}
break;
case "mobile":
if (!this.form[item.rules.name]) {
uni.showToast({
title: "手机号不能为空",
duration: 2000,
icon: "none",
});
throw Error(); //
}
if (!/^\s{0}$|^1\d{10}$/.test(this.form[item.rules.name])) {
uni.showToast({
title: "手机格式错误",
duration: 2000,
icon: "none",
});
throw Error(); //
}
break;
default:
if (!this.form[item.rules.name]) {
uni.showToast({
title: item.rules.errMess || item.label + "不能为空",
duration: 2000,
icon: "none",
});
throw Error(); //
}
if (item.rules.regexp && !(new RegExp(item.rules.regexp).test(this.form[item.rules.name]))) {
uni.showToast({
title: item.label + "格式不正确",
duration: 2000,
icon: "none",
});
throw Error(); //
}
break;
}
}
});
resolve(this.form)
})
},
//
resetForm() {
for (let key in this.form) {
if (this.form.hasOwnProperty(key)) {
switch (typeof this.form[key]) {
case "object":
this.form[key] = []
break
case "number":
this.form[key] = ''
break
case "string":
this.form[key] = ''
break
}
}
}
this.$emit("input", this.form);
}
//
// $submitForm() {
// const formData = this.formData
// console.log("formData :>> ", formData);
// let submitData = {};
// for (let i = 0; i < formData.length; i++) {
// if (formData[i].type === 'file') {
// submitData[formData[i].rules.name] = formData[i].rules.fileList;
// continue;
// }
// submitData[formData[i].rules.name] = formData[i].rules.value;
// }
// return submitData;
// }
},
};
</script>
<style lang="scss" scoped>
.active-form {
min-height: 200px;
.plaClass {
text-align: right;
font-size: 26rpx;
}
.input-placeholder {
display: flex;
justify-content: flex-end;
font-size: 26rpx;
color: grey;
}
// icon
.select-icon {
float: right;
border-bottom: 2rpx solid #999;
border-right: 2rpx solid #999;
width: 16rpx;
height: 16rpx;
transform: rotate(-45deg);
margin-right: 10rpx;
}
.form-box {
width: 100%;
box-sizing: border-box;
}
.colorRed {
color: red;
padding: 0 10rpx;
}
.line-right {
flex: 1;
height: 100%;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
}
.line-bottom-select {
padding-top: 40rpx;
}
.line-bottom-textarea {
padding-top: 20rpx;
textarea {
min-height: 100rpx;
}
}
.line-left {
display: flex;
min-width: 22%;
align-items: center;
height: 100%;
letter-spacing: 0.5px;
font-size: 26rpx;
color: #000000;
box-sizing: border-box;
}
.p-l14 {
padding-left: 34rpx;
}
.textarea-box {
width: 100%;
border-bottom: 1px solid #ededed;
padding-top: 20rpx;
font-size: 26rpx;
textarea {
padding-left: 32rpx;
height: 100rpx;
font-size: 25rpx;
color: #333;
}
}
.line {
padding: 27rpx 0;
display: flex;
align-items: center;
width: 100%;
margin: 0 auto;
border-bottom: 1px solid #ededed;
overflow: hidden;
.input {
padding-right: 20rpx;
padding-left: 20rpx;
height: 100%;
width: 100%;
text-align: left;
font-size: 28rpx;
color: #333;
border: none;
overflow: hidden;
text-overflow: ellipsis;
outline: none;
}
}
.line-col {
padding: 27rpx 0;
display: flex;
flex-direction: column;
width: 100%;
margin: 0 auto;
border-bottom: 1px solid #ededed;
overflow: hidden;
.input {
padding-right: 20rpx;
height: 100%;
width: 100%;
text-align: left;
font-size: 28rpx;
color: #333;
border: none;
overflow: hidden;
text-overflow: ellipsis;
outline: none;
}
}
.num {
margin-right: 8rpx;
}
}
</style>

760
src/components/active-form/active-form222.vue

@ -0,0 +1,760 @@
<template>
<view class="active-form form-container">
<view class="form-box">
<block v-for="(item, index) in formData" :key="item.id">
<view class="form-item flex-row--c">
<!-- 单行文本框 -->
<view
class="line"
v-if="
item.type === 'text' ||
item.type === 'number' ||
item.type === 'code'
"
>
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view>
<!-- 发送验证码 -->
<view
class="line-right flex-row-sb-c pr20"
v-if="item.type === 'code'"
>
<input
type="text"
class="input"
:disabled="item.disabled"
placeholder-class="plaClass"
:placeholder="item.placeholder"
v-model="form[item.rules.name]"
@input="inputVal(index)"
/>
<view style="width:250rpx">
<u-button
size="mini"
type="primary"
:disabled="item.disabled||isSend"
@click="sendCode(item)"
>
{{ codeFont }}
</u-button>
</view>
</view>
<!-- 普通输入框 -->
<view class="line-right" v-else>
<input
type="text"
class="input"
:disabled="item.disabled"
placeholder-class="plaClass"
:placeholder="item.placeholder"
v-model="form[item.rules.name]"
@input="inputVal(index)"
/>
</view>
</view>
<!-- 下拉选择-->
<template v-else-if="item.type === 'select'">
<view class="line" @click="showSelect(item)">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view>
<view class="line-right pr20">
<view class="input plaClass">
<text>
{{
item.list.find(v => v.value === form[item.rules.name]) && item.list.find(v => v.value === form[item.rules.name]).name || ''
}}
</text>
<text class="input-placeholder" v-if="!form[item.rules.name]">{{
item.placeholder
}}
</text>
</view>
<u-icon name="arrow-down-fill"></u-icon>
</view>
</view>
<u-action-sheet :actions="item.list"
:title="item.title"
safeAreaInsetBottom
round="40"
cancelText="取消"
:show="item.show"
@select="selectConfirm($event,item)"
@close="selectClose(item)"
></u-action-sheet>
</template>
<block v-else-if="item.type === 'datetime'">
<view class="line" @click="showSelect(item)">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view>
<view class="line-right pr20">
<view class="input plaClass">
<text>{{ form[item.rules.name] }}</text>
<text class="input-placeholder" v-if="!form[item.rules.name]">{{
item.placeholder
}}
</text>
</view>
<u-icon name="arrow-down-fill"></u-icon>
</view>
</view>
时间{{item.params}}
<u-picker
:mode="'time'"
v-model="item.show"
:params="item.params"
@confirm="selectDateTime($event,item)">
</u-picker>
</block>
<!-- 多行文本框 -->
<view class="textarea-box" v-else-if="item.type === 'textarea'">
<view :class="item.rules.verify ? '' : 'p-l14 '">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view>
<view class="line-bottom-textarea">
<!-- placeholder-class="plaClass" -->
<textarea
style="color: #a7a7a7; font-size: 24rpx"
auto-height
:maxlength="-1"
:disabled="item.disabled"
:placeholder="item.placeholder"
v-model="form[item.rules.name]"
@input="inputVal(index)"
>
</textarea>
</view>
</view>
<!-- 上传图片 -->
<view class="img-box pt30 flex-col-l" v-else-if="item.type === 'file'">
<view class="font26" :class="item.rules.verify ? '' : 'p-l14 '">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view>
<view class="img-upload p30">
<u-upload
:fileList="form[item.rules.name]"
:disabled="item.disabled"
:accept="item.accept"
:capture="item.capture"
:maxCount="item.maxCount"
:sizeType="item.sizeType"
:compressed="item.compressed"
:camera="item.camera"
:multiple="item.multiple"
:maxSize="item.maxSize"
:previewImage="item.previewImage"
width="150rpx"
height="150rpx"
@afterRead="afterRead($event,item)"
@delete="deletePic($event,item)"
></u-upload>
</view>
</view>
<!-- 单选框 -->
<view class="line-col" v-else-if="item.type === 'radio'">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
<text
style="
font-size: 20rpx;
color: #9e9e9e;
margin-left: 23rpx;
width: 140rpx;
"
>(单选)
</text>
</view>
<view
class="line-bottom-select"
:style="{ 'padding-left': num ? '60rpx' : '34rpx' }"
>
<u-radio-group
v-model="form[item.rules.name]"
@change="radioChange($event, index)"
placement="row"
>
<u-radio
:size="35"
:icon-size="35"
:label-size="25"
shape="circle"
v-for="(radioItem, radioIndex) in item.list"
:key="radioIndex"
:disabled="radioItem.disabled"
>
{{radioItem.name}}
</u-radio>
</u-radio-group>
</view>
</view>
<!-- 多选框 -->
<view class="line-col" v-else-if="item.type === 'checkbox'">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
<text
style="
font-size: 20rpx;
color: #9e9e9e;
margin-left: 23rpx;
width: 140rpx;
"
>(多选)
</text>
</view>
<view
class="line-bottom-select pr20"
:style="{ 'padding-left': num ? '60rpx' : '34rpx' }"
>
<u-checkbox-group
v-model="form[item.rules.name]"
@change="checkboxGroupChange($event,item)"
>
<u-checkbox
icon-size="25rpx"
label-size="25rpx"
size="30rpx"
v-for="(checkboxItem, checkboxIndex) in item.list"
:key="checkboxIndex"
:label="checkboxItem.label"
:disabled="checkboxItem.disabled"
:name="checkboxItem.value"
>
</u-checkbox>
</u-checkbox-group>
</view>
</view>
<!-- 手机输入框 -->
<view class="line" v-else-if="item.type === 'mobile'">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view>
<view class="line-right pr20">
<input
type="number"
v-model="form[item.rules.name]"
:placeholder="item.placeholder"
@input="inputVal(index)"
class="input"
:disabled="item.disabled"
:maxlength="11"
placeholder-class="plaClass"
/>
<view style="width:200rpx" v-if="item.oneKeyPhone">
<u-button
size="mini"
type="primary"
open-type="getPhoneNumber"
@getphonenumber="getphonenumber"
:disabled="item.disabled"
>一键获取
</u-button>
</view>
</view>
</view>
</view>
</block>
</view>
</view>
</template>
<script>
import mixins from "./mixins";
export default {
name: "activeForm",
mixins: [mixins],
props: {
//
num: {
type: Boolean,
default: false,
},
value: {
type: Object,
default: () => {
return {};
},
},
formData: {
type: Array,
default: () => {
return [];
},
},
//
isEdit: {
type: Boolean,
default: false,
},
//
isDel: {
type: Boolean,
default: false,
},
},
data() {
return {
submitData: "",
selectBox: [],
currentSelectIndex: "",
currentSelectValue: "",
codeFont: "获取验证码",
wait: 60,
isSend: false,
form: {},//form//
};
},
computed: {
// formData: {
// get() {
// // console.log("this.formData", this.value)
// return this.value
// },
// set(nval) {
// this.$emit("input", nval);
// }
// }
},
mounted() {
setTimeout(() => {
this.dataFormat()
})
},
methods: {
//
dataFormat() {
let formDefault = this.extractRules(this.formData)
let formValue = this.value
let form = Object.assign(formDefault, formValue)
console.log("form", form)
this.$set(this, 'form', form)
},
//keyvalue
extractRules(formData) {
const extractedRules = {};
formData.forEach(field => {
const {rules} = field;
if (rules.name) {
extractedRules[rules.name] = rules.value;
}
});
return extractedRules;
},
//
deletePic($event, item) {
item.rules.value.splice($event.index, 1)
this.form[item.rules.name] = item.rules.value
this.$emit('input', this.form)
},
//
afterRead($event, item) {
// mutiple true , file
item.rules.value = item.multiple ? $event.file : [$event.file]
this.form[item.rules.name] = item.rules.value
this.$emit('input', this.form)
},
//select
showSelect(item) {
item.show = true;
this.$emit('input', this.form)
this.$forceUpdate()
},
//input
inputVal(index) {
const data = {
val: this.formData[index].rules.value,
index: index,
};
if (String(data.val) !== "" && String(data.index) !== "") {
this.formData[data.index].rules.value = data.val;
}
this.$emit("input", this.form);
},
//
selectConfirm($event, item) {
item.rules.value = $event.value;
this.form[item.rules.name] = $event.value;
item.show = false
this.$emit("input", this.form);
this.$forceUpdate()
},
selectCalendar($event, item) {
const dateString = $event.reduce((b, n) => (b + `,${n}`))
console.log("selectCalendar", dateString)
// item.rules.label = dateString;
this.form[item.rules.name] = item.rules.value = dateString;
item.show = false
this.$emit("input", this.form);
this.$forceUpdate()
},
// value:mode:
selectDateTime($event, item) {
const formatValue = $event.mode === 'time' ? this.formatTime(this.getTimestampFromTime($event.value), $event.mode) : this.formatTime($event.value, $event.mode)
// item.rules.label = formatValue
this.form[item.rules.name] = item.rules.value = item.returnTimestamp ? ($event.mode === 'time' ? this.getTimestampFromTime($event.value) : $event.value) : formatValue; //
item.show = false
this.$emit("input", this.form);
this.$forceUpdate()
},
// datetimeyear-month ,datetime
formatTime(timestamp, formatType) {
const date = new Date(timestamp);
if (isNaN(date)) {
return "Invalid Date";
}
let year = date.getFullYear();
let month = String(date.getMonth() + 1).padStart(2, "0");
let day = String(date.getDate()).padStart(2, "0");
let hours = String(date.getHours()).padStart(2, "0");
let minutes = String(date.getMinutes()).padStart(2, "0");
let seconds = String(date.getSeconds()).padStart(2, "0");
switch (formatType) {
case "date":
return `${year}-${month}-${day}`;
case "time":
return `${hours}:${minutes}`; //:${seconds}
case "year-month":
return `${year}-${month}`;
case "datetime":
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
default:
return "Invalid Format Type";
}
},
// "11:00"
getTimestampFromTime(inputTime) {
//
const currentDate = new Date();
//
const [hours, minutes] = inputTime.split(':');
//
const targetDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDate(), hours, minutes);
//
const timestamp = targetDate.getTime();
return timestamp;
},
selectClose(item) {
item.show = false;
this.$forceUpdate()
},
//
radioChange($event, index) {
this.$emit("input", this.form);
},
//
checkboxGroupChange($event, item) {
// console.log("$event", $event)
const selectArr = item.list.filter((v => ($event.includes(v.label)))) //
// console.log("selectArr", selectArr)
this.form[item.rules.name] = item.rules.value = selectArr.map(v => (v.value))
this.$emit("input", this.form);
},
//
sendCode(item) {
let setTime = 0;
this.sendCodeCallback(item)
if (!this.isSend) {
this.isSend = true;
setTime = setInterval(() => {
this.wait--;
this.codeFont = this.wait + "重新发送";
if (this.wait === 0) {
clearInterval(setTime);
this.codeFont = "获取验证码";
this.isSend = false;
this.wait = 60;
}
}, 1000);
}
},
//
vervify() {
return new Promise((resolve, reject) => {
this.formData.forEach((item) => {
if (item.rules.verify) {
switch (item.type) {
case "checkbox":
if (this.form[item.rules.name].length === 0) {
uni.showToast({
title: item.rules.errMess || "请选择" + item.label,
duration: 2000,
icon: "none",
});
throw Error(); //
}
break;
case "file":
if (this.form[item.rules.name].length === 0) {
uni.showToast({
title: item.rules.errMess || "请选择" + item.label,
duration: 2000,
icon: "none",
});
throw Error(); //
}
break;
case "mobile":
if (!this.form[item.rules.name]) {
uni.showToast({
title: "手机号不能为空",
duration: 2000,
icon: "none",
});
throw Error(); //
}
if (!/^\s{0}$|^1\d{10}$/.test(this.form[item.rules.name])) {
uni.showToast({
title: "手机格式错误",
duration: 2000,
icon: "none",
});
throw Error(); //
}
break;
default:
if (!this.form[item.rules.name]) {
uni.showToast({
title: item.rules.errMess || item.label + "不能为空",
duration: 2000,
icon: "none",
});
throw Error(); //
}
if (item.rules.regexp && !(new RegExp(item.rules.regexp).test(this.form[item.rules.name]))) {
uni.showToast({
title: item.label + "格式不正确",
duration: 2000,
icon: "none",
});
throw Error(); //
}
break;
}
}
});
resolve(this.form)
})
},
//
resetForm() {
for (let key in this.form) {
if (this.form.hasOwnProperty(key)) {
switch (typeof this.form[key]) {
case "object":
this.form[key] = []
break
case "number":
this.form[key] = ''
break
case "string":
this.form[key] = ''
break
}
}
}
this.$emit("input", this.form);
}
//
// $submitForm() {
// const formData = this.formData
// console.log("formData :>> ", formData);
// let submitData = {};
// for (let i = 0; i < formData.length; i++) {
// if (formData[i].type === 'file') {
// submitData[formData[i].rules.name] = formData[i].rules.fileList;
// continue;
// }
// submitData[formData[i].rules.name] = formData[i].rules.value;
// }
// return submitData;
// }
},
};
</script>
<style lang="scss" scoped>
.active-form {
min-height: 200px;
.plaClass {
text-align: right;
font-size: 26rpx;
}
.input-placeholder {
display: flex;
justify-content: flex-end;
font-size: 26rpx;
color: grey;
}
// icon
.select-icon {
float: right;
border-bottom: 2rpx solid #999;
border-right: 2rpx solid #999;
width: 16rpx;
height: 16rpx;
transform: rotate(-45deg);
margin-right: 10rpx;
}
.form-box {
width: 100%;
box-sizing: border-box;
}
.colorRed {
color: red;
padding: 0 10rpx;
}
.line-right {
flex: 1;
height: 100%;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
}
.line-bottom-select {
padding-top: 40rpx;
}
.line-bottom-textarea {
padding-top: 20rpx;
textarea {
min-height: 100rpx;
}
}
.line-left {
display: flex;
min-width: 22%;
align-items: center;
height: 100%;
letter-spacing: 0.5px;
font-size: 26rpx;
color: #000000;
box-sizing: border-box;
}
.p-l14 {
padding-left: 34rpx;
}
.textarea-box {
width: 100%;
border-bottom: 1px solid #ededed;
padding-top: 20rpx;
font-size: 26rpx;
textarea {
padding-left: 32rpx;
height: 100rpx;
font-size: 25rpx;
color: #333;
}
}
.line {
padding: 27rpx 0;
display: flex;
align-items: center;
width: 100%;
margin: 0 auto;
border-bottom: 1px solid #ededed;
overflow: hidden;
.input {
padding-right: 20rpx;
padding-left: 20rpx;
height: 100%;
width: 100%;
text-align: left;
font-size: 28rpx;
color: #333;
border: none;
overflow: hidden;
text-overflow: ellipsis;
outline: none;
}
}
.line-col {
padding: 27rpx 0;
display: flex;
flex-direction: column;
width: 100%;
margin: 0 auto;
border-bottom: 1px solid #ededed;
overflow: hidden;
.input {
padding-right: 20rpx;
height: 100%;
width: 100%;
text-align: left;
font-size: 28rpx;
color: #333;
border: none;
overflow: hidden;
text-overflow: ellipsis;
outline: none;
}
}
.num {
margin-right: 8rpx;
}
}
</style>

452
src/components/active-form/detail.md

@ -0,0 +1,452 @@
# 导入即用 全端支持
### 2.0插件地址 https://ext.dcloud.net.cn/plugin?id=5842 (基于uview2.0)
### 1.0插件地址 https://ext.dcloud.net.cn/plugin?id=8755 (基于uview1.0)
#### 注意!!!
```
本插件基于 uview2.0进行重构 使用需要引入uview2.0支持
[ 点击uview2.0官网地址 ](https://www.uviewui.com/)
[引入uview2.0指南](https://ext.dcloud.net.cn/plugin?id=1593)
```
### 有问题 可评论 看到及时回复
# 使用方式
## 1. 注册
### App.vue引入组件样式即可
```javascript
<script>
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style lang="scss">
/*每个页面公共css */
@import "@/components/active-form/active-form.scss";//注入active-form样式
</style>
```
## 2.页面使用
```javascript
<template>
<view class="content">
<active-form ref="activeForm" v-model="form" :formData="formData" num></active-form>
<view class="btn-list">
<view class="subform" @click="submit">提交表单</view>
<view class="resetform" @click="reset">重置表单</view>
</view>
</view>
</template>
<script>
import ActiveForm from "@/components/active-form/active-form";
export default {
components: {
ActiveForm,
},
data() {
return {
//双向绑定回显
form: {
age: 2,
// createTime:"00:03"
// photo: [{url: 'https://uviewui.com/common/logo.png'}],
// sex:1
},
//表单配置项
formData: [
{
id: "sad31asgh",
placeholder: "请选择年龄段",
label: "年龄",
type: "radio",
list: [
{
value: 1,
label: "15岁以下",
},
{
value: 2,
label: "16~20岁",
},
{
value: 3,
label: "21~25岁",
},
{
value: 4,
label: "26~30岁",
},
{
value: 5,
label: "31~40岁",
},
{
value: 6,
label: "40岁以上",
},
],
rules: {
name: "age",
value: 1, // 字段值 list.value 填入回显 0 1
verify: true,
errMess: "请选择年龄段",
},
},
{
id: "kjj32nggg22112sas2asd",
placeholder: "未选择获客时间",
label: "获客时间",
type: "datetime",
mode: 'datetime',// date为日期选择,time为时间选择,year-month为年月选择 ,datetime日期时间选择
returnTimestamp: false, //value值是否返回时间搓格式
// maxDate: new Date(new Date().getFullYear() + 10, 0, 1).getTime(),//可选的最大时间(时间戳毫秒)
// minDate: new Date(new Date().getFullYear() - 10, 0, 1).getTime(),//可选的最小时间(时间戳毫秒)
// minHour: 0,//可选的最小小时,仅mode=time有效
// maxHour: 23,//可选的最大小时,仅mode=time有效
// minMinute: 0,//可选的最小分钟,仅mode=time有效
// maxMinute: 59,//可选的最大分钟,仅mode=time有效
show: false,
rules: {
name: "createTime",
value: "",
verify: false,
errMess: "未选择获客时间",
},
},
{
id: "kjj32nsa123s232asd",
placeholder: "选择日期",
label: "日期",
type: "calendar",
mode: 'multiple',// mode为single只能选择单个日期 为multiple可以选择多个日期为range可以选择日期范围
returnTimestamp: false, //value值是否返回时间搓格式
show: false,
rules: {
name: "calendarDate",
value: "",
verify: false,
errMess: "未选择获客时间",
},
},
{
id: "kjjn123sasd",
placeholder: "输入名字",
label: "姓名",
type: "text",
disabled: false,
rules: {
name: "name",
value: "",
verify: true,
errMess: "姓名未填写",
regexp: '^1' //正则校验
},
},
{
id: "kjjnsas123d",
placeholder: "输入验证码",
label: "验证码",
type: "code",
disabled: false,//是否禁用
rules: {
name: "code",
value: "",
verify: true,
errMess: "验证码未填写",
},
// 发送验证码回调 由于小程序props传递函数会丢失(此处无效) 此回调方法在组建内部书写 方法在目录active-form/mixins.js中自定义书写
// sendCodeCallback() {
//
// }
},
{
id: "uisd123fjks",
placeholder: "请输入手机号",
label: "手机",
type: "mobile",
rules: {
name: "mobile",
value: "", //字段值
verify: true,
errMess: "手机号格式不正确",
},
oneKeyPhone: true, //是否开启微信点击获取手机号
//微信获取手机号回调 和参数oneKeyPhone配套 由于小程序props传递函数会丢失(此处无效) 方法在目录active-form/mixins.js中自定义书写
// getphonenumber({details}) {
//
// }
},
{
id: "ukhjgas12dsas",
placeholder: "选择",
label: "性别",
type: "select",
show: false, //是否显示
title: "请选择性别",
list: [
{
value: 1,
name: "男",
},
{
value: 2,
name: "女",
},
],
rules: {
name: "sex",
value: "", //list.value 0 1
verify: false,
errMess: "性别未选择",
},
},
{
id: "gdfjZjnx",
placeholder: "请输入地址信息",
label: "地址 ",
type: "text",
rules: {
name: "location",
value: "",
verify: false,
errMess: "地址不能为空",
},
},
{
id: "asdfd11fgd",
label: "孩子头像 ",
type: "file",
maxCount: 1, //最大选择图片的数量
multiple: false, //是否开启图片多选,部分安卓机型不支持 false true
accept: 'image',//接受的文件类型,file只支持H5(只有微信小程序才支持把accept配置为all、media) 可选 all | media | image | file | video
capture: ['album', 'camera'],// 图片或视频拾取模式,当accept为image类型时设置capture可选额外camera可以直接调起摄像头 String | Array
sizeType: ['original', 'compressed'],//original 原图,compressed 压缩图,默认二者都有,H5无效
compressed: true,//当accept为video时生效,是否压缩视频,默认为true Boolean true false
camera: 'back', //当accept为video时生效,可选值为back或front String back -
maxSize: Number.MAX_VALUE,// 选择单个文件的最大大小,单位B(byte),默认不限制 String | Number
previewImage: true,//是否在上传完成后展示预览图 Boolean true false
disabled: false,//是否禁用
rules: {
name: "photo",
value: [],//显示已上传的文件列表 回显 [{url:'https://xxx.cn'}]
verify: true,
errMess: "请选择头像",
},
},
{
id: "gdoodsndf",
placeholder: "请选择兴趣",
label: "兴趣",
type: "checkbox",
list: [
{
value: 1,
label: "篮球",
disabled: true,//是否禁用
},
{
value: 2,
label: "足球",
},
{
value: 3,
label: "羽毛球",
},
{
value: 4,
label: "唱歌",
},
{
value: 5,
label: "街舞",
},
{
value: 6,
label: "yyds",
},
{
value: 7,
label: "跳舞",
},
{
value: 8,
label: "看剧",
},
{
value: 9,
label: "洗澡",
},
],
rules: {
name: "interest",
value: [7], //字段值 0 1
verify: false,
errMess: "请选择年龄段",
},
},
{
id: "kopty53mk",
placeholder: "请输入公司名称",
label: "公司",
type: "text",
rules: {
name: "company",
value: "",
verify: false,
errMess: "公司名称不能为空",
},
},
{
id: "asd3453fgf",
placeholder: "(例如:平面设计、品牌设计、UI设计)",
label: "是否有设计相关经历?",
type: "textarea",
rules: {
name: "experience",
value: "", //字段值
verify: true,
errMess: "请输入经历",
},
},
],
};
},
methods: {
// 提交表单
submit() {
this.$refs.activeForm.vervify()
.then(async (form) => {
console.log("表单对象:", form);
})
.catch((err) => {
console.log("err", err);
}); //表单校验
},
//重置表单
reset() {
this.$refs.activeForm.resetForm()
}
},
};
</script>
<style lang="less">
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.btn-list {
display: flex;
.subform {
margin: 30rpx;
padding: 20rpx 60rpx;
border-radius: 18rpx;
background-color: bisque;
}
.resetform {
margin: 30rpx;
padding: 20rpx 60rpx;
border-radius: 18rpx;
background-color: #6e6a67;
color: #ffffff;
}
}
}
</style>
```
# 组件参数
### 1.组件props
| 参数名 | 类型 | 是否必填 | 介绍 |
| ------------- | ------------- | ---- | -----------------------------------------------------------------------------|
| form | Object | 是 | v-model双向绑定(若要回显在此处定义,表单值) |
| formData | Array | 是 | 表单配置项option
| num | Boolean 默认false | 是 | 每个表单项前面是否带有序号
### 2.formData 项参数说明 (type=datetime、calendar ,部分参数参考uview2.0官方文档)
| 参数名 | 类型 | 是否必填 | 介绍 |
| ------------- | ------------- | ---- | ----------------------------------------------------------------------------- |
| id | String number | 是 | 必填索引 不唯一 |
| placeholder | String | 是 | 提示
| label | String | 是 | 开头标题 |
| type | String | 是 | 该表单项类型 当前支持 text(文本)、 number、 mobile、code(验证码)、 radio、 checkbox、 file(照片,文件)、 select(上拉选择)、calendar(日期选择) 、 datetime(时间选择)|
| list | Array | 是 | type为 radio、 checkbox、select时有效
| list[index].disabled | Boolean | 否 | type为 radio、 checkbox、select时有效
| disabled | Boolean | 否 | type为 radio、 checkbox、select时有效
| rules.errMess | String | 是 | 校验不通过时的错误提示 |
| rules.name | String | 是 | 接收字段名 后端接收的字段 |
| rules.value | String Array | 否 | 默认值(一开始显示),回显使用form对象 |
| rules.verify | Boolean | 否 | 是否校验该字段
| rules.regexp | String | 否 | 正侧校验字段
### 3.校验方法
| 事件名 | 返回参数 | 简介 |
| --------------------------- | ------ | ---------------------- |
| vervify() | null | *表单校验 成功会继续往下走 失败抛出异常* |
| resetForm(); | null | *重置表单* |
```javascript
##记得组件绑定ref
methods: {
// 提交表单
submit() {
this.$refs.activeForm.vervify()
.then(async (form) => {
console.log("表单对象:", form);
})
.catch((err) => {
console.log("err", err);
}); //表单校验
},
//重置表单
reset() {
this.$refs.activeForm.resetForm()
}
},
```
```
### 4.由于小程序props传递函数会丢失(此处无效) 选项回调方法在目录active-form/mixins.js中自定义书写
```javascript
export default {
data() {
return {}
},
methods: {
// 微信小程序获取手机号
async getphonenumber({detail}) {
},
// 获取验证码回调 此处调用api接口 并赋值
async sendCodeCallback(item) {
// item.rules.value =
}
}
}
```

15
src/components/active-form/mixins.js

@ -0,0 +1,15 @@
export default {
data() {
return {}
},
methods: {
// 微信小程序获取手机号
async getphonenumber({detail}) {
},
// 获取验证码回调 此处调用api接口 并赋值
async sendCodeCallback(item) {
// item.rules.value =
}
}
}

387
src/components/active-formv1/detail.md

@ -0,0 +1,387 @@
#### 注意!!!
```
本插件基于 uview1.0进行重构 使用需要引入uview1.0支持
[ 点击uview1.0官网地址 ](https://www.uviewui.com/)
```
### 有问题 可评论 看到及时回复
## 2.页面使用
```javascript
<template>
<view class="content">
<active-form ref="activeForm" v-model="formData" num></active-form>
<view class="subform"
@click="sub">提交表单
</view>
</view>
</template>
<script>
import ActiveForm from "@/components/activeForm";
export default {
components: {
ActiveForm,
},
data() {
return {
formData: [{
id: "sadasgh",
placeholder: "请选择年龄段",
label: "年龄",
type: "radio",
list: [{
value: 1,
label: "15岁以下",
},
{
value: 2,
label: "16~20岁",
},
{
value: 3,
label: "21~25岁",
},
{
value: 4,
label: "26~30岁",
},
{
value: 5,
label: "31~40岁",
},
{
value: 6,
label: "40岁以上",
},
],
rules: {
name: "age",
value: 1, // 字段值 list.value 填入回显 0 1
verify: false,
errMess: "请选择年龄段",
},
},
{
id: "kjj32nsasasd",
placeholder: "未选择获客时间",
label: "获客时间",
type: "time",
show: false,
params: {
year: true,
month: true,
day: true,
hour: false,
minute: false,
second: false,
// 选择时间的时间戳
// timestamp: true,
},
rules: {
name: "createTime",
value: "",
verify: false,
errMess: "未选择获客时间",
},
},
{
id: "kjjnsasd",
placeholder: "输入名字",
label: "姓名",
type: "text",
disabled: false,
rules: {
name: "name",
value: "",
verify: true,
errMess: "姓名未填写",
regexp: '^赵' //正则校验
},
},
{
id: "kjjnsasd",
placeholder: "输入验证码",
label: "验证码",
type: "code",
disabled: true, //是否禁用
rules: {
name: "code",
value: "",
verify: true,
errMess: "验证码未填写",
},
// 发送验证码回调 由于小程序props传递函数会丢失(此处无效) 此回调方法在组建内部书写 方法在目录active-form/mixins.js中自定义书写
// sendCodeCallback() {
//
// }
},
{
id: "uisdfjks",
placeholder: "请输入手机号",
label: "手机",
type: "mobile",
rules: {
name: "mobile",
value: "", //字段值
verify: true,
errMess: "手机号格式不正确",
},
oneKeyPhone: false, //是否开启微信点击获取手机号
//微信获取手机号回调 和参数oneKeyPhone配套 由于小程序props传递函数会丢失(此处无效) 方法在目录active-form/mixins.js中自定义书写
// getphonenumber({details}) {
//
// }
},
{
id: "ukhjgasdsas",
placeholder: "选择",
label: "性别",
type: "select",
show: false, //是否显示
title: "请选择性别",
list: [{
value: 1,
name: "男",
},
{
value: 2,
name: "女",
},
],
rules: {
name: "sex",
value: "", //list.value 0 1
label: "", // list.name 填入回显 '男'
verify: false,
errMess: "性别未选择",
},
},
{
id: "gdfjZjnx",
placeholder: "请输入地址信息",
label: "地址 ",
type: "text",
rules: {
name: "location",
value: "",
verify: false,
errMess: "地址不能为空",
},
},
{
id: "asdfdfgd",
label: "孩子头像 ",
type: "file",
accept: 'image', //接受的文件类型,file只支持H5(只有微信小程序才支持把accept配置为all、media) 可选 all | media | image | file | video
capture: ['album',
'camera'], // 图片或视频拾取模式,当accept为image类型时设置capture可选额外camera可以直接调起摄像头 String | Array
maxCount: 2, //最大选择图片的数量
sizeType: ['original', 'compressed'], //original 原图,compressed 压缩图,默认二者都有,H5无效
compressed: true, //当accept为video时生效,是否压缩视频,默认为true Boolean true false
camera: 'back', //当accept为video时生效,可选值为back或front String back -
multiple: false, //是否开启图片多选,部分安卓机型不支持 false true
maxSize: Number.MAX_VALUE, // 选择单个文件的最大大小,单位B(byte),默认不限制 String | Number
previewImage: true, //是否在上传完成后展示预览图 Boolean true false
disabled: false, //是否禁用
rules: {
name: "photo",
fileList: [], //显示已上传的文件列表 回显 [{url:'https://xxx.cn'}]
verify: true,
errMess: "请选择头像",
},
},
{
id: "oodsndf",
placeholder: "请选择兴趣",
label: "兴趣",
type: "checkbox",
list: [{
value: 1,
name: "篮球",
disabled: true, //是否禁用
checked: false,
},
{
value: 2,
name: "足球",
checked: false,
},
{
value: 3,
name: "羽毛球",
checked: false,
},
{
value: 4,
name: "唱歌",
checked: false,
},
{
value: 5,
name: "街舞",
checked: false,
},
{
value: 6,
name: "yyds",
checked: false,
},
{
value: 7,
name: "跳舞",
checked: false,
},
{
value: 8,
name: "看剧",
checked: false,
},
{
value: 9,
name: "洗澡",
checked: false,
},
],
rules: {
name: "interest",
value: [8], //字段值 0 1
verify: false,
errMess: "请选择年龄段",
},
},
{
id: "koptymk",
placeholder: "请输入公司名称",
label: "公司",
type: "text",
rules: {
name: "company",
value: "",
verify: false,
errMess: "公司名称不能为空",
},
},
{
id: "asdfgf",
placeholder: "(例如:平面设计、品牌设计、UI设计)",
label: "是否有设计相关经历?",
type: "textarea",
rules: {
name: "experience",
value: "", //字段值
verify: true,
errMess: "请输入经历",
},
},
],
};
},
methods: {
// 提交表单
sub() {
this.$refs.activeForm.$vervify().then(async form => {
console.log('表单对象:', form);
}).catch(err => {
console.log("err", err)
})
},
},
};
</script>
<style lang="less">
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.subform {
margin: 30rpx;
padding: 20rpx 60rpx;
border-radius: 18rpx;
background-color: bisque;
}
}
</style>
```
# 组件参数
### 1.组件props
参数名 | 类型 | 介绍 |
| -------- | --------------- | ------------------------ |
| formDate | Array | v-model双向绑定 |
| num | Boolean 默认false | 每个表单项前面是否带有序号
### 2.form 项参数说明
| 参数名 | 类型 | 是否必填 | 介绍 |
| ------------- | ------------- | ---- | ----------------------------------------------------------------------------- |
| id | String number | 是 | 必填索引 不唯一 |
| placeholder | String | 是 | 提示
| label | String | 是 | 开头标题 |
| type | String | 是 | 该表单项类型 当前支持 text(文本)、textarea、 number、 mobile、code(验证码)、 radio、 checkbox、 file(照片,文件)、 select(上拉选择) |
| list | Array | 是 | type为 radio、 checkbox、select时有效
| list[index].disabled | Boolean | 否 | type为 radio、 checkbox、select时有效
| disabled | Boolean | 否 | 是否禁用输入 type为 text、 number、mobile 、code 、file、textarea时有效
| rules.errMess | String | 是 | 校验不通过时的错误提示 |
| rules.name | String | 是 | 接收字段名 后端接收的字段 |
| rules.value | String Array | 否 | 字段值 |
| rules.label | String Array | 是 | 是否校验该字段
| rules.verify | Boolean | 否 | 是否校验该字段
| rules.regexp | String | 否 | 正侧校验字段
| rules.fileList | Array | 是 |type为file时的 文件类型参数
### 3.校验方法
| 事件名 | 返回参数 | 简介 |
| --------------------------- | ------ | ---------------------- |
| $vervify(this.formData) | null | *表单校验 成功会继续往下走 失败抛出异常* |
| $submitForm(this.formData); | 表单字段对象 | *校验成功 获取表单值* |
```javascript
<script>
export default {
methods: {
//点击提交按钮时触发 提交表单 this.formData为使用者定义的生成表单的js串
sub() {
this.$refs.activeForm.$vervify().then(async form => {
console.log('表单对象:', form);
}).catch(err => {
console.log("err", err)
})
},
},
};
```
### 4.由于小程序props传递函数会丢失(此处无效) 选项回调方法在目录active-form/mixins.js中自定义书写
```javascript
export default {
data() {
return {}
},
methods: {
// 微信小程序获取手机号
async getphonenumber({detail}) {
},
// 获取验证码回调 此处调用api接口 并赋值
async sendCodeCallback(item) {
// item.rules.value =
}
}
}
```

550
src/components/active-formv1/index.vue

@ -0,0 +1,550 @@
<template>
<view class="form-container">
<view class="form-box">
<block v-for="(item, index) in formData" :key="index">
<view class=" " style="width: 100%;">
<!-- 单行文本框 -->
<view class="line" style="display: flex; flex-direction: column; width: 100%;"
v-if="item.type=='input'">
<view :class="item.rules.verify ? '' : 'p-l14 '" style="display: flex; flex-direction: column;">
<view class=""
style="display: flex;flex-direction: row; align-items: center; border-bottom: #9e9e9e;">
<view class="">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
</view>
<view class="" style="display: flex;flex-direction: column;">
<view class="content">
内容 : {{ item.content }}
</view>
</view>
</view>
</view>
<!-- 普通输入框 -->
<view class="" style="width: 100%;">
<input :type="item.type" class="input" placeholder-class="" :placeholder="item.placeholder"
v-model="item.rules.value" :disabled="item.disabled" @input="inputVal(index)" />
</view>
<view class="methond">
方法 : {{item.methond}}
</view>
</view>
<view v-else-if="item.type=='select'">
<view :class="item.rules.verify ? '' : 'p-l14 '" style="display: flex; flex-direction: column;">
<view class=""
style="display: flex;flex-direction: row; align-items: center; border-bottom: #9e9e9e;">
<view class="">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
</view>
<view class="" style="display: flex;flex-direction: column;">
<view class="content">
内容 : {{ item.content }}
</view>
</view>
</view>
</view>
<view class="" style="display: flex; flex-direction: row;">
<input disabled type="text" class="input" placeholder-class="plaClass"
:placeholder="item.placeholder" v-model="item.rules.label" @click="item.show = true" />
</view>
<u-select :title="item.title" v-model="item.show" :list="item.list" value-name="value"
label-name="name" @confirm="selectConfirm($event,item)"></u-select>
<view class="methond">
方法 : {{item.methond}}
</view>
</view>
<view v-else-if="item.type=='selectAndInput'">
<view :class="item.rules.verify ? '' : 'p-l14 '" style="display: flex; flex-direction: column;">
<view class=""
style="display: flex;flex-direction: row; align-items: center; border-bottom: #9e9e9e;">
<view class="">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
</view>
<view class="" style="display: flex;flex-direction: column;">
<view class="content">
内容 : {{ item.content }}
</view>
</view>
</view>
</view>
<uni-combox :candidates="item.list" :placeholder="item.placeholder" v-model="item.rules.value"></uni-combox>
<view class="methond">
方法 : {{item.methond}}
</view>
</view>
</view>
</block>
</view>
</view>
</template>
<script>
import mixins from "./mixins";
export default {
name: "activeForm",
mixins: [mixins],
data() {
return {
submitData: "",
selectBox: [],
currentSelectIndex: "",
currentSelectValue: "",
codeFont: "获取验证码",
wait: 60,
isSend: false,
sendColor: "color:#ff5b01",
};
},
props: {
//
num: {
type: Boolean,
default: false,
},
formData: {
type: Array,
default: () => {
return [];
},
},
},
computed: {
// formData: {
// get() {
// // checkbox
// this.value.forEach(item => {
// if (item.type === "checkbox") {
// item.list.forEach(item2 => {
// item2.checked = item.rules.value.includes(item2.value)
// })
// }
// })
// console.log("this.formData", this.value)
// return this.value
// },
// set(nval) {
// this.$emit("input", nval);
// }
// }
},
methods: {
//input
inputVal(index) {
const data = {
val: this.formData[index].rules.value,
index: index,
};
if (String(data.val) != "" && String(data.index) != "") {
this.formData[data.index].rules.value = data.val;
}
this.$emit("input", this.formData);
},
//
selectConfirm($event, item) {
item.rules.label = $event[0].label;
item.rules.value = $event[0].value;
this.$emit("input", this.formData);
// console.log("this.formData", this.formData)
},
selectTime({
year,
month,
day,
hour,
minute,
second
}, item) {
let date = ''
if (year) {
date += year + '-'
}
if (month) {
date += month + '-'
}
if (day) {
date += day
}
if (hour) {
date += ' ' + hour
}
if (minute) {
date += ':' + minute
}
if (second) {
date += ':' + second
}
item.rules.value = date
item.rules.label = date;
this.$emit("input", this.formData);
console.log("this.formData", this.formData)
},
//
radioChange($event, index) {
this.$emit("input", this.formData);
console.log("this.formData", this.formData)
},
//
checkboxGroupChange($event, item) {
console.log("param; :>> ", $event, item);
item.rules.value = $event;
this.$emit("input", this.formData);
},
//
deletePic($event, item) {
item.rules.fileList.splice($event.index, 1)
this.$emit('input', this.formData)
console.log("this.formData", this.formData)
},
//
afterRead($event, item) {
// mutiple true , file
console.log("$event, item", $event, item)
item.rules.fileList = item.multiple ? $event : $event
this.$emit('input', this.formData)
console.log("this.formData", this.formData)
},
//
$vervify1111() {
var test=""
return new Promise((resolve, reject) => {
for (var i = 0; i < this.formData.length; i++) {
var item =this.formData[i]
if(item.rules.verify){
switch (item.type) {
case "input":
if (item.rules.value.length === 0) {
console.log("打印"+item.rules.errMess)
uni.showToast({
title: item.rules.errMess || "请选择" + item.label,
duration: 2000,
icon: "none",
});
reject(false)
// throw Error(); //
}
break;
case "file":
if (item.rules.fileList.length === 0) {
uni.showToast({
title: item.rules.errMess || "请选择" + item.label,
duration: 2000,
icon: "none",
});
reject(false)
}
break;
default:
if ([null, undefined, ''].includes(item.rules.value)) {
uni.showToast({
title: item.rules.errMess || item.label + "不能为空",
duration: 2000,
icon: "none",
});
reject(false)
// throw Error(); //
}
break;
}
}
}
resolve(this.$submitForm())
})
},
//
$vervify() {
return new Promise((resolve, reject) => {
for (var i = 0; i < this.formData.length; i++) {
var item =this.formData[i]
if(item.rules.verify){
if(item.type=="input"||item.type=="select"||item.type=="selectAndInput"){
if (item.rules.value.length === 0) {
console.log("打印"+item.rules.errMess)
uni.showToast({
title: item.rules.errMess || "请选择" + item.label,
duration: 2000,
icon: "none",
});
reject(false)
break;
// throw Error(); //
}
}
}
}
resolve(this.$submitForm())
})
},
//
$submitForm() {
const formData = this.formData
let submitData = {};
for (let i = 0; i < formData.length; i++) {
if (formData[i].type === 'file') {
submitData[formData[i].rules.name] = formData[i].rules.fileList;
break;
}
submitData[formData[i].rules.name] = formData[i].rules.value;
}
return submitData;
},
//
resetForm() {
// for (let key in this.formData) {
// if (this.formData.hasOwnProperty(key)) {
// switch (typeof this.formData[key]) {
// case "object":
// this.formData[key] = []
// break
// case "number":
// this.formData[key] = ''
// break
// case "string":
// this.formData[key] = ''
// break
// }
// }
// }
// this.$emit("input", this.formData);
for (let item of this.formData) {
if(item.type=='select'){
item.rules.name = ""
}else {
item.rules.value = ""
}
}
this.$emit("input", this.formData);
}
},
};
</script>
<style lang="scss" scoped>
.img-box {
padding-top: 30rpx;
.img-upload {
padding-top: 30rpx;
}
}
//
.select-modal {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 300000;
.select-bg {
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
}
.select-box {
position: absolute;
left: 0;
bottom: -1000upx;
width: 100%;
background: #fff;
max-height: 50%;
// height: 0%;
overflow: auto;
.select-title {
display: flex;
justify-content: space-between;
height: 80rpx;
background: #f5f5f5;
line-height: 80rpx;
padding: 0 30rpx;
}
.select-item {
font-size: 28rpx;
color: #333;
border-bottom: 1px solid #eee;
height: 75rpx;
line-height: 75rpx;
padding: 0 30rpx;
i {
display: block;
float: right;
border-bottom: 4rpx solid #1ca032;
border-right: 4rpx solid #1ca032;
width: 12rpx;
height: 26rpx;
transform: rotate(45deg);
margin-top: 24.5rpx;
}
}
}
}
// icon
.select-icon {
float: right;
border-bottom: 2rpx solid #999;
border-right: 2rpx solid #999;
width: 16rpx;
height: 16rpx;
transform: rotate(-45deg);
margin-right: 30rpx;
}
.color-999 {
color: #999;
}
.plaClass {
text-align: center;
font-size: 26rpx;
}
.form-container {
width: 100%;
.form-box {
width: 100%;
box-sizing: border-box;
}
.colorRed {
color: red;
padding: 0 10rpx;
}
.line-right {
flex: 1;
height: 100%;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
}
.line-bottom-select {
padding-top: 40rpx;
}
.line-bottom-textarea {
padding-top: 20rpx;
textarea {
min-height: 100rpx;
}
}
.line-left {
display: flex;
min-width: 22%;
align-items: center;
height: 100%;
letter-spacing: 0.5px;
font-size: 26rpx;
// font-weight: 550;
color: #000000;
box-sizing: border-box;
}
.p-l14 {
padding-left: 34rpx;
}
.textarea-box {
// display: flex;
width: 100%;
border-bottom: 1px solid #ededed;
padding-top: 20rpx;
// align-items: center;
textarea {
padding-left: 32rpx;
height: 100rpx;
font-size: 25rpx;
color: #333;
}
}
.line {
padding: 27rpx 0;
// min-height: 100rpx;
display: flex;
width: 100%;
// margin: 0 auto;
border-bottom: 1px solid #ededed;
// overflow: hidden;
}
.num {
margin-right: 8rpx;
font-size: 35rpx;
}
.input {
padding: 10rpx;
height: 100%;
text-align: left;
margin: 10rpx;
font-size: 28rpx;
color: #333;
border: none;
overflow: hidden;
text-overflow: ellipsis;
outline: none;
border-radius: 10rpx;
border: 1rpx solid lightgrey;
}
.content {
font-size: 32rpx;
}
.methond {
margin-left: 50rpx;
font-size: 29rpx;
color: #999;
}
}
</style>

704
src/components/active-formv1/index1.vue

@ -0,0 +1,704 @@
<template>
<view class="form-container">
<view class="form-box">
<block v-for="(item, index) in formData" :key="item.rules.name">
<view class="form-item flex-row--c">
<!-- 单行文本框 -->
<view class="line" v-if="['text','password','number','code'].includes(item.type)">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'"
>
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view
>
<!-- 发送验证码 -->
<view class="line-right send-code-box" v-if="item.type === 'code'">
<input
:type="item.type"
class="input"
placeholder-class="plaClass"
:placeholder="item.placeholder"
v-model="item.rules.value"
@input="inputVal(index)"
/>
<view style="width:250rpx">
<u-button
size="mini"
type="primary"
:disabled="item.disabled||isSend"
@click="sendCode(item)"
>
{{ codeFont }}
</u-button>
</view>
</view>
<!-- 普通输入框 -->
<view class="line-right" v-else>
<input
:type="item.type"
class="input"
placeholder-class="plaClass"
:placeholder="item.placeholder"
v-model="item.rules.value"
:disabled="item.disabled"
@input="inputVal(index)"
/>
</view>
</view>
<!-- 下拉选择-->
<view class="line" v-else-if="['select','time'].includes(item.type)">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'"
>
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view
>
<view class="line-right">
<input
disabled
type="text"
class="input"
placeholder-class="plaClass"
:placeholder="item.placeholder"
v-model="item.rules.label"
@click="item.show = true"
/>
<view class="select-icon"></view>
</view>
<u-select
v-if="item.type === 'select'"
:title="item.title"
v-model="item.show"
:list="item.list"
value-name="value"
label-name="name"
@confirm="selectConfirm($event,item)"
></u-select>
<!--类型为时间-->
<u-picker v-else-if="item.type === 'time'"
:params="item.params"
mode="time"
v-model="item.show"
@confirm="selectTime($event,item)">
</u-picker>
</view>
<!-- 多行文本框 -->
<view class="textarea-box" v-else-if="item.type == 'textarea'">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'"
>
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view
>
<view class="line-bottom-textarea">
<textarea
rows=""
style="color: #a7a7a7; font-size: 28rpx"
auto-height
:maxlength="-1"
cols=""
placeholder-class="plaClass"
:disabled="item.disabled"
:placeholder="item.placeholder"
v-model="item.rules.value"
@input="inputVal(index)"
>
</textarea>
</view>
</view>
<!-- 上传图片 -->
<view class="img-box flex-col-l" v-else-if="item.type == 'file'">
<view style="font-size:26rpx" :class="item.rules.verify ? '' : 'p-l14 '">
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view>
<view class="img-upload p30">
<u-upload
:auto-upload="false"
:fileList="item.rules.fileList"
:disabled="item.disabled"
:accept="item.accept"
:capture="item.capture"
:maxCount="item.maxCount"
:sizeType="item.sizeType"
:compressed="item.compressed"
:camera="item.camera"
:multiple="item.multiple"
:maxSize="item.maxSize"
:previewImage="item.previewImage"
width="150rpx"
height="150rpx"
@on-choose-complete="afterRead($event,item)"
@on-remove="deletePic($event,item)"
></u-upload>
</view>
</view>
<!-- 单选框 -->
<view class="line-col" v-else-if="item.type === 'radio'">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'"
>
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
<text style="font-size: 20rpx; color: #9e9e9e; margin-left: 23rpx; width: 140rpx">(单选)
</text>
</view
>
<view class="line-bottom-select" :style="{ 'padding-left': num ? '60rpx' : '34rpx' }">
<u-radio-group :currentIndex="index" v-model="item.rules.value"
@change="radioChange($event, index)">
<u-radio
icon-size="35"
label-size="25"
shape="circle"
v-for="(radioItem, radioIndex) in item.list"
:key="radioIndex"
:name="radioItem.value"
:disabled="radioItem.disabled"
>{{ radioItem.label }}
</u-radio
>
</u-radio-group>
</view>
</view>
<!-- 多选框 -->
<view class="line-col" v-else-if="item.type == 'checkbox'">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'"
>
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
<text style="font-size: 20rpx; color: #9e9e9e; margin-left: 23rpx; width: 140rpx">(多选)
</text>
</view>
<view class="line-bottom-select" :style="{ 'padding-left': num ? '60rpx' : '34rpx' }">
<u-checkbox-group @change="checkboxGroupChange($event,item)">
<u-checkbox
icon-size="35"
label-size="25"
v-model="checkboxItem.checked"
v-for="(checkboxItem, checkboxIndex) in item.list"
:key="checkboxIndex"
:name="checkboxItem.value"
:disabled="checkboxItem.disabled"
>{{ checkboxItem.name }}
</u-checkbox
>
</u-checkbox-group>
</view>
</view>
<!-- 手机输入框 -->
<view class="line" v-else-if="item.type === 'mobile'">
<view :class="item.rules.verify ? 'line-left' : 'p-l14 line-left'"
>
<text class="colorRed" v-if="item.rules.verify">*</text>
<text class="num" v-if="num">{{ index + 1 }}.</text>
{{ item.label }}
</view
>
<view class="line-right">
<input
type="number"
v-model="item.rules.value"
:placeholder="item.placeholder"
@input="inputVal(index)"
class="input"
:maxlength="11"
/>
<view style="width:250rpx">
<u-button
v-if="item.oneKeyPhone"
size="mini"
type="primary"
open-type="getPhoneNumber"
@getphonenumber="getphonenumber"
:disabled="item.disabled"
>一键获取
</u-button>
</view>
</view>
</view>
</view>
</block>
</view>
</view>
</template>
<script>
import mixins from "./mixins";
export default {
name: "activeForm",
mixins: [mixins],
data() {
return {
submitData: "",
selectBox: [],
currentSelectIndex: "",
currentSelectValue: "",
codeFont: "获取验证码",
wait: 60,
isSend: false,
sendColor: "color:#ff5b01",
};
},
props: {
//
num: {
type: Boolean,
default: false,
},
formData: {
type: Array,
default: () => {
return [];
},
},
},
computed: {
// formData: {
// get() {
// // checkbox
// this.value.forEach(item => {
// if (item.type === "checkbox") {
// item.list.forEach(item2 => {
// item2.checked = item.rules.value.includes(item2.value)
// })
// }
// })
// console.log("this.formData", this.value)
// return this.value
// },
// set(nval) {
// this.$emit("input", nval);
// }
// }
},
methods: {
//input
inputVal(index) {
const data = {
val: this.formData[index].rules.value,
index: index,
};
if (String(data.val) != "" && String(data.index) != "") {
this.formData[data.index].rules.value = data.val;
}
this.$emit("input", this.formData);
},
//
selectConfirm($event, item) {
item.rules.label = $event[0].label;
item.rules.value = $event[0].value;
this.$emit("input", this.formData);
// console.log("this.formData", this.formData)
},
selectTime({year, month, day, hour, minute, second}, item) {
let date = ''
if (year) {
date += year + '-'
}
if (month) {
date += month + '-'
}
if (day) {
date += day
}
if (hour) {
date += ' ' + hour
}
if (minute) {
date += ':' + minute
}
if (second) {
date += ':' + second
}
item.rules.value = date
item.rules.label = date;
this.$emit("input", this.formData);
console.log("this.formData", this.formData)
},
//
radioChange($event, index) {
this.$emit("input", this.formData);
console.log("this.formData", this.formData)
},
//
checkboxGroupChange($event, item) {
console.log("param; :>> ", $event, item);
item.rules.value = $event;
this.$emit("input", this.formData);
},
//
deletePic($event, item) {
item.rules.fileList.splice($event.index, 1)
this.$emit('input', this.formData)
console.log("this.formData", this.formData)
},
//
afterRead($event, item) {
// mutiple true , file
console.log("$event, item", $event, item)
item.rules.fileList = item.multiple ? $event : $event
this.$emit('input', this.formData)
console.log("this.formData", this.formData)
},
//
sendCode(item) {
let setTime = 0;
this.sendCodeCallback(item)
if (!this.isSend) {
this.isSend = true;
setTime = setInterval(() => {
this.wait--;
this.codeFont = this.wait + "重新发送";
if (this.wait === 0) {
clearInterval(setTime);
this.codeFont = "获取验证码";
this.isSend = false;
this.wait = 60;
}
}, 1000);
}
},
//
$vervify() {
return new Promise((resolve, reject) => {
this.formData.forEach((item) => {
if (item.rules.verify) {
switch (item.type) {
case "checkbox":
if (item.rules.value.length === 0) {
uni.showToast({
title: item.rules.errMess || "请选择" + item.label,
duration: 2000,
icon: "none",
});
reject(false)
// throw Error(); //
}
break;
case "file":
if (item.rules.fileList.length === 0) {
uni.showToast({
title: item.rules.errMess || "请选择" + item.label,
duration: 2000,
icon: "none",
});
reject(false)
// throw Error(); //
}
break;
case "mobile":
if (!item.rules.value) {
uni.showToast({
title: item.rules.errMess || "手机号不能为空",
duration: 2000,
icon: "none",
});
reject(false)
// throw Error(); //
}
if (!/^\s{0}$|^1\d{10}$/.test(item.rules.value)) {
uni.showToast({
title: "手机格式错误",
duration: 2000,
icon: "none",
});
reject(false)
// throw Error(); //
}
break;
default:
if ([null, undefined, ''].includes(item.rules.value)) {
uni.showToast({
title: item.rules.errMess || item.label + "不能为空",
duration: 2000,
icon: "none",
});
reject(false)
// throw Error(); //
}
if (item.rules.regexp && !(new RegExp(item.rules.regexp).test(item.rules.value))) {
uni.showToast({
title: item.label + "格式不正确",
duration: 2000,
icon: "none",
});
reject(false)
// throw Error(); //
}
break;
}
}
});
resolve(this.$submitForm())
})
},
//
$submitForm() {
const formData = this.formData
let submitData = {};
for (let i = 0; i < formData.length; i++) {
if (formData[i].type === 'file') {
submitData[formData[i].rules.name] = formData[i].rules.fileList;
break;
}
submitData[formData[i].rules.name] = formData[i].rules.value;
}
return submitData;
},
//
resetForm() {
// for (let key in this.formData) {
// if (this.formData.hasOwnProperty(key)) {
// switch (typeof this.formData[key]) {
// case "object":
// this.formData[key] = []
// break
// case "number":
// this.formData[key] = ''
// break
// case "string":
// this.formData[key] = ''
// break
// }
// }
// }
// this.$emit("input", this.formData);
for (let item of this.formData) {
item.rules.value =""
}
this.$emit("input", this.formData);
}
},
};
</script>
<style lang="scss" scoped>
.img-box{
padding-top: 30rpx;
.img-upload{
padding-top: 30rpx;
}
}
//
.select-modal {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 300000;
.select-bg {
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.3);
}
.select-box {
position: absolute;
left: 0;
bottom: -1000upx;
width: 100%;
background: #fff;
max-height: 50%;
// height: 0%;
overflow: auto;
.select-title {
display: flex;
justify-content: space-between;
height: 80rpx;
background: #f5f5f5;
line-height: 80rpx;
padding: 0 30rpx;
}
.select-item {
font-size: 28rpx;
color: #333;
border-bottom: 1px solid #eee;
height: 75rpx;
line-height: 75rpx;
padding: 0 30rpx;
i {
display: block;
float: right;
border-bottom: 4rpx solid #1ca032;
border-right: 4rpx solid #1ca032;
width: 12rpx;
height: 26rpx;
transform: rotate(45deg);
margin-top: 24.5rpx;
}
}
}
}
// icon
.select-icon {
float: right;
border-bottom: 2rpx solid #999;
border-right: 2rpx solid #999;
width: 16rpx;
height: 16rpx;
transform: rotate(-45deg);
margin-right: 30rpx;
}
.color-999 {
color: #999;
}
.plaClass {
text-align: right;
font-size: 26rpx;
}
.form-container {
.form-box {
width: 100%;
box-sizing: border-box;
}
.colorRed {
color: red;
padding: 0 10rpx;
}
.line-right {
flex: 1;
height: 100%;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
}
.line-bottom-select {
padding-top: 40rpx;
}
.line-bottom-textarea {
padding-top: 20rpx;
textarea {
min-height: 100rpx;
}
}
.line-left {
display: flex;
min-width: 22%;
align-items: center;
height: 100%;
letter-spacing: 0.5px;
font-size: 26rpx;
// font-weight: 550;
color: #000000;
box-sizing: border-box;
}
.p-l14 {
padding-left: 34rpx;
}
.textarea-box {
// display: flex;
width: 100%;
border-bottom: 1px solid #ededed;
padding-top: 20rpx;
// align-items: center;
textarea {
padding-left: 32rpx;
height: 100rpx;
font-size: 25rpx;
color: #333;
}
}
.line {
padding: 27rpx 0;
// min-height: 100rpx;
display: flex;
align-items: center;
width: 100%;
margin: 0 auto;
border-bottom: 1px solid #ededed;
overflow: hidden;
.input {
padding-right: 20rpx;
padding-left: 20rpx;
height: 100%;
width: 100%;
text-align: left;
font-size: 28rpx;
color: #333;
border: none;
overflow: hidden;
text-overflow: ellipsis;
outline: none;
}
}
.line-col {
padding: 27rpx 0;
// min-height: 100rpx;
display: flex;
flex-direction: column;
width: 100%;
margin: 0 auto;
border-bottom: 1px solid #ededed;
overflow: hidden;
.input {
padding-right: 20rpx;
height: 100%;
width: 100%;
text-align: left;
font-size: 28rpx;
color: #333;
border: none;
overflow: hidden;
text-overflow: ellipsis;
outline: none;
}
}
.num {
margin-right: 8rpx;
}
}
</style>

15
src/components/active-formv1/mixins.js

@ -0,0 +1,15 @@
export default {
data() {
return {}
},
methods: {
// 微信小程序获取手机号
async getphonenumber({detail}) {
},
// 获取验证码回调 此处调用api接口 并赋值
async sendCodeCallback(item) {
// item.rules.value =
}
}
}

181
src/components/amap-wx/js/util.js

@ -0,0 +1,181 @@
import amap from '@/components/amap-wx/lib/amap-wx.js';
// 地铁颜色图
const line = {
'1号线': '#C43B33',
'2号线': '#016299',
'4号线/大兴线': '#008E9C',
'5号线': '#A42380',
'6号线': '#D09900',
'7号线': '#F2C172',
'8号线': '#009D6A',
'9号线': '#8FC41E',
'10号线': '#009DBE',
'13号线': '#F9E701',
'14号线东段': '#D4A7A2',
'14号线西段': '#D4A7A2',
'15号线': '#5D2D69',
'八通线': '#C33A32',
'昌平线': '#DE82B1',
'亦庄线': '#E40177',
'房山线': '#E66021',
'机场线': '#A29BBC',
}
// 150500:地铁站 ,150700:公交站 , 190700:地名地址
const typecode = [{
id: '150500',
icon: 'icon-ditie'
}, {
id: '150700',
icon: 'icon-gongjiao'
}, {
id: '190700',
icon: 'icon-gonglu'
}];
const util = {
key:'b526b09b86cd2996e7732be8ab8c4430',
/**
* 初始化高德地图api
*/
mapInit() {
return new amap.AMapWX({
key: this.key
});
},
// 服务状态吗
typecode,
/**
* 获取地图颜色
*/
lineColor(name) {
if (line[name]) {
return line[name];
} else {
return '#ccc';
}
},
/**
* 关键字颜色变化
*/
serachNmme(val, name) {
let namestr = new RegExp(val);
let nameresult =
`<div style="font-size: 14px;color: #333;line-height: 1.5;">
${name.replace(namestr, "<span style='color:#66ccff;'>" + val + '</span>')}
</div>`
.trim();
return nameresult;
},
/**
* 地址转地铁线路
*/
addressToLine(address, type) {
let addr = address.split(';');
let dt = '';
addr.forEach(elm => {
let color = '#cccccc';
if (type === typecode[0].id) {
color = this.lineColor(elm)
} else if (type === typecode[1].id) {
color = '#4075cb'
}
let style = 'margin:5px 0;margin-right:5px;padding:0 5px;background:' + color +
';font-size:12px;color:#fff;border-radius:3px;';
dt += `<div style=\'${style}\'>${elm}</div>`;
});
return `<div style="display:flex;flex-wrap: wrap;">${dt}</div>`;
},
/**
* 数据处理
*/
dataHandle(item, val) {
// 改变字体颜色
if (val) {
item.nameNodes = util.serachNmme(val, item.name);
} else {
item.nameNodes = `<div style="font-size: 14px;color: #333;line-height: 1.5;">${item.name}</div>`;
}
// 地址解析 地铁
if (
item.typecode === util.typecode[0].id ||
item.typecode === util.typecode[1].id
) {
item.addressNodes = util.addressToLine(item.address, item.typecode);
if (item.typecode === util.typecode[0].id) {
item.icon = util.typecode[0].icon;
} else if (item.typecode === util.typecode[1].id) {
item.icon = util.typecode[1].icon;
}
} else {
item.addressNodes = `<span>${item.district}${
item.address.length > 0 ? '·' + item.address : ''
}</span>`.trim();
item.icon = 'icon-weizhi';
}
if (item.location && item.location.length === 0) {
item.icon = 'icon-sousuo';
}
return item;
},
/**
* 存储历史数据
* val [string | object]需要存储的内容
*/
setHistory(val) {
let searchHistory = uni.getStorageSync('search:history');
if (!searchHistory) searchHistory = [];
let serachData = {};
if (typeof(val) === 'string') {
serachData = {
adcode: [],
address: [],
city: [],
district: [],
id: [],
location: [],
name: val,
typecode: []
};
} else {
serachData = val
}
// 判断数组是否存在,如果存在,那么将放到最前面
for (var i = 0; i < searchHistory.length; i++) {
if (searchHistory[i].name === serachData.name) {
searchHistory.splice(i, 1);
break;
}
}
searchHistory.unshift(util.dataHandle(serachData));
uni.setStorage({
key: 'search:history',
data: searchHistory,
success: function() {
// console.log('success');
}
});
},
getHistory() {
},
removeHistory() {
uni.removeStorage({
key: 'search:history',
success: function(res) {
console.log('success');
}
});
return []
}
}
export default util;

1
src/components/amap-wx/lib/amap-wx.js

File diff suppressed because one or more lines are too long

39
src/components/custom-nomore/custom-nomore.vue

@ -0,0 +1,39 @@
<!-- z-paging自定义的没有更多数据view -->
<template>
<view class="nomore">
<!-- 这里的图片请换成自己项目的图片 -->
<image class="nomore-image" mode="aspectFit" src="@/static/no_more.png"></image>
<text class="nomore-text">已经到达宇宙尽头啦~</text>
</view>
</template>
<script>
export default {
data() {
return {
};
}
}
</script>
<style scoped>
.nomore{
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
align-items: center;
padding: 20rpx 0px;
}
.nomore-image{
width: 200rpx;
height: 130rpx;
}
.nomore-text{
margin-top: 10rpx;
font-size: 24rpx;
color: #222963;
}
</style>

58
src/components/custom-refresher/custom-refresher.vue

@ -0,0 +1,58 @@
<!-- z-paging自定义的下拉刷新view -->
<template>
<view class="refresher-container">
<!-- 这里的图片请换成自己项目的图片 -->
<image class="refresher-image" mode="aspectFit" src="@/static/refresher_loading.gif"></image>
<text class="refresher-text">{{statusText}}</text>
</view>
</template>
<script>
export default {
data() {
return {
};
},
computed: {
statusText() {
// i18nuni.getLocale()(i18n-demo.vue);
//
const statusTextArr = ['哎呀,用点力继续下拉!', '拉疼我啦,松手刷新~~', '正在努力刷新中...', '刷新成功啦~'];
return statusTextArr[this.status];
}
},
props: {
status: {
type: Number,
default: function() {
return 0;
},
},
}
}
</script>
<style scoped>
.refresher-container {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
height: 150rpx;
flex-direction: column;
align-items: center;
justify-content: center;
}
.refresher-image {
margin-top: 10rpx;
height: 45px;
width: 45px;
}
.refresher-text {
margin-top: 10rpx;
font-size: 24rpx;
color: #666666;
}
</style>

1
src/components/marked/index.js

@ -0,0 +1 @@
export default './lib/marked'

1573
src/components/marked/lib/marked.js

File diff suppressed because it is too large

12542
src/components/mpvue-citypicker/city-data/area.js

File diff suppressed because it is too large

1503
src/components/mpvue-citypicker/city-data/city.js

File diff suppressed because it is too large

139
src/components/mpvue-citypicker/city-data/province.js

@ -0,0 +1,139 @@
/* eslint-disable */
var provinceData = [{
"label": "北京市",
"value": "11"
},
{
"label": "天津市",
"value": "12"
},
{
"label": "河北省",
"value": "13"
},
{
"label": "山西省",
"value": "14"
},
{
"label": "内蒙古自治区",
"value": "15"
},
{
"label": "辽宁省",
"value": "21"
},
{
"label": "吉林省",
"value": "22"
},
{
"label": "黑龙江省",
"value": "23"
},
{
"label": "上海市",
"value": "31"
},
{
"label": "江苏省",
"value": "32"
},
{
"label": "浙江省",
"value": "33"
},
{
"label": "安徽省",
"value": "34"
},
{
"label": "福建省",
"value": "35"
},
{
"label": "江西省",
"value": "36"
},
{
"label": "山东省",
"value": "37"
},
{
"label": "河南省",
"value": "41"
},
{
"label": "湖北省",
"value": "42"
},
{
"label": "湖南省",
"value": "43"
},
{
"label": "广东省",
"value": "44"
},
{
"label": "广西壮族自治区",
"value": "45"
},
{
"label": "海南省",
"value": "46"
},
{
"label": "重庆市",
"value": "50"
},
{
"label": "四川省",
"value": "51"
},
{
"label": "贵州省",
"value": "52"
},
{
"label": "云南省",
"value": "53"
},
{
"label": "西藏自治区",
"value": "54"
},
{
"label": "陕西省",
"value": "61"
},
{
"label": "甘肃省",
"value": "62"
},
{
"label": "青海省",
"value": "63"
},
{
"label": "宁夏回族自治区",
"value": "64"
},
{
"label": "新疆维吾尔自治区",
"value": "65"
},
{
"label": "台湾",
"value": "66"
},
{
"label": "香港",
"value": "67"
},
{
"label": "澳门",
"value": "68"
}
]
export default provinceData;

230
src/components/mpvue-citypicker/mpvueCityPicker.vue

@ -0,0 +1,230 @@
<template>
<div class="mpvue-picker">
<div :class="{'pickerMask':showPicker}" @click="maskClick" catchtouchmove="true"></div>
<div class="mpvue-picker-content " :class="{'mpvue-picker-view-show':showPicker}">
<div class="mpvue-picker__hd" catchtouchmove="true">
<div class="mpvue-picker__action" @click="pickerCancel">取消</div>
<div class="mpvue-picker__action" :style="{color:themeColor}" @click="pickerConfirm">确定</div>
</div>
<picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue" @change="pickerChange">
<block>
<picker-view-column>
<div class="picker-item" v-for="(item,index) in provinceDataList" :key="index">{{item.label}}</div>
</picker-view-column>
<picker-view-column>
<div class="picker-item" v-for="(item,index) in cityDataList" :key="index">{{item.label}}</div>
</picker-view-column>
<picker-view-column>
<div class="picker-item" v-for="(item,index) in areaDataList" :key="index">{{item.label}}</div>
</picker-view-column>
</block>
</picker-view>
</div>
</div>
</template>
<script>
import provinceData from './city-data/province.js';
import cityData from './city-data/city.js';
import areaData from './city-data/area.js';
export default {
data() {
return {
pickerValue: [0, 0, 0],
provinceDataList: provinceData,
cityDataList: cityData[0],
areaDataList: areaData[0][0],
/* 是否显示控件 */
showPicker: false,
};
},
created() {
this.init()
},
props: {
/* 默认值 */
pickerValueDefault: {
type: Array,
default () {
return [0, 0, 0]
}
},
/* 主题色 */
themeColor: String
},
watch: {
pickerValueDefault() {
this.init();
}
},
methods: {
init() {
this.handPickValueDefault(); // pickerValueDefault
const pickerValueDefault = this.pickerValueDefault
this.cityDataList = cityData[pickerValueDefault[0]];
this.areaDataList = areaData[pickerValueDefault[0]][pickerValueDefault[1]];
this.pickerValue = pickerValueDefault;
},
show() {
setTimeout(() => {
this.showPicker = true;
}, 0);
},
maskClick() {
this.pickerCancel();
},
pickerCancel() {
this.showPicker = false;
this._$emit('onCancel');
},
pickerConfirm(e) {
this.showPicker = false;
this._$emit('onConfirm');
},
showPickerView() {
this.showPicker = true;
},
handPickValueDefault() {
const pickerValueDefault = this.pickerValueDefault
let provinceIndex = pickerValueDefault[0]
let cityIndex = pickerValueDefault[1]
const areaIndex = pickerValueDefault[2]
if (
provinceIndex !== 0 ||
cityIndex !== 0 ||
areaIndex !== 0
) {
if (provinceIndex > provinceData.length - 1) {
this.pickerValueDefault[0] = provinceIndex = provinceData.length - 1;
}
if (cityIndex > cityData[provinceIndex].length - 1) {
this.pickerValueDefault[1] = cityIndex = cityData[provinceIndex].length - 1;
}
if (areaIndex > areaData[provinceIndex][cityIndex].length - 1) {
this.pickerValueDefault[2] = areaData[provinceIndex][cityIndex].length - 1;
}
}
},
pickerChange(e) {
let changePickerValue = e.mp.detail.value;
if (this.pickerValue[0] !== changePickerValue[0]) {
//
this.cityDataList = cityData[changePickerValue[0]];
this.areaDataList = areaData[changePickerValue[0]][0];
changePickerValue[1] = 0;
changePickerValue[2] = 0;
} else if (this.pickerValue[1] !== changePickerValue[1]) {
//
this.areaDataList =
areaData[changePickerValue[0]][changePickerValue[1]];
changePickerValue[2] = 0;
}
this.pickerValue = changePickerValue;
this._$emit('onChange');
},
_$emit(emitName) {
let pickObj = {
label: this._getLabel(),
value: this.pickerValue,
cityCode: this._getCityCode()
};
this.$emit(emitName, pickObj);
},
_getLabel() {
let pcikerLabel =
this.provinceDataList[this.pickerValue[0]].label +
'-' +
this.cityDataList[this.pickerValue[1]].label +
'-' +
this.areaDataList[this.pickerValue[2]].label;
return pcikerLabel;
},
_getCityCode() {
return this.areaDataList[this.pickerValue[2]].value;
}
}
};
</script>
<style>
.pickerMask {
position: fixed;
z-index: 1000;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
}
.mpvue-picker-content {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
transition: all 0.3s ease;
transform: translateY(100%);
z-index: 3000;
}
.mpvue-picker-view-show {
transform: translateY(0);
}
.mpvue-picker__hd {
display: flex;
padding: 9px 15px;
background-color: #fff;
position: relative;
text-align: center;
font-size: 17px;
}
.mpvue-picker__hd:after {
content: ' ';
position: absolute;
left: 0;
bottom: 0;
right: 0;
height: 1px;
border-bottom: 1px solid #e5e5e5;
color: #e5e5e5;
transform-origin: 0 100%;
transform: scaleY(0.5);
}
.mpvue-picker__action {
display: block;
flex: 1;
color: #1aad19;
}
.mpvue-picker__action:first-child {
text-align: left;
color: #888;
}
.mpvue-picker__action:last-child {
text-align: right;
}
.picker-item {
text-align: center;
line-height: 40px;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 16px;
}
.mpvue-picker-view {
position: relative;
bottom: 0;
left: 0;
width: 100%;
height: 238px;
background-color: rgba(255, 255, 255, 1);
}
</style>

123
src/components/mpvue-echarts/src/echarts.vue

@ -0,0 +1,123 @@
<template>
<canvas v-if="canvasId" class="ec-canvas" :id="canvasId" :canvasId="canvasId" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd" @error="error"></canvas>
</template>
<script>
import WxCanvas from './wx-canvas';
export default {
props: {
canvasId: {
type: String,
default: 'ec-canvas'
},
lazyLoad: {
type: Boolean,
default: false
},
disableTouch: {
type: Boolean,
default: false
},
throttleTouch: {
type: Boolean,
default: false
}
},
// #ifdef H5
mounted() {
if (!this.lazyLoad) this.init();
},
// #endif
// #ifndef H5
onReady() {
if (!this.lazyLoad) this.init();
},
// #endif
methods: {
setChart(chart){
this.chart = chart
},
init() {
const { canvasId } = this;
this.ctx = wx.createCanvasContext(canvasId, this);
this.canvas = new WxCanvas(this.ctx, canvasId);
const query = wx.createSelectorQuery().in(this);
query
.select(`#${canvasId}`)
.boundingClientRect(res => {
if (!res) {
setTimeout(() => this.init(), 50);
return;
}
this.$emit('onInit', {
width: res.width,
height: res.height
});
})
.exec();
},
canvasToTempFilePath(opt) {
const { canvasId } = this;
this.ctx.draw(true, () => {
wx.canvasToTempFilePath({
canvasId,
...opt
});
});
},
touchStart(e) {
const { disableTouch, chart } = this;
if (disableTouch || !chart || !e.mp.touches.length) return;
const touch = e.mp.touches[0];
chart._zr.handler.dispatch('mousedown', {
zrX: touch.x,
zrY: touch.y
});
chart._zr.handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y
});
},
touchMove(e) {
const { disableTouch, throttleTouch, chart, lastMoveTime } = this;
if (disableTouch || !chart || !e.mp.touches.length) return;
if (throttleTouch) {
const currMoveTime = Date.now();
if (currMoveTime - lastMoveTime < 240) return;
this.lastMoveTime = currMoveTime;
}
const touch = e.mp.touches[0];
chart._zr.handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y
});
},
touchEnd(e) {
const { disableTouch, chart } = this;
if (disableTouch || !chart) return;
const touch = e.mp.changedTouches ? e.mp.changedTouches[0] : {};
chart._zr.handler.dispatch('mouseup', {
zrX: touch.x,
zrY: touch.y
});
chart._zr.handler.dispatch('click', {
zrX: touch.x,
zrY: touch.y
});
}
}
};
</script>
<style scoped>
.ec-canvas {
width: 100%;
height: 100%;
flex: 1;
}
</style>

73
src/components/mpvue-echarts/src/wx-canvas.js

@ -0,0 +1,73 @@
export default class WxCanvas {
constructor(ctx, canvasId) {
this.ctx = ctx;
this.canvasId = canvasId;
this.chart = null;
WxCanvas.initStyle(ctx);
this.initEvent();
}
getContext(contextType) {
return contextType === '2d' ? this.ctx : null;
}
setChart(chart) {
this.chart = chart;
}
attachEvent() {
// noop
}
detachEvent() {
// noop
}
static initStyle(ctx) {
const styles = ['fillStyle', 'strokeStyle', 'globalAlpha',
'textAlign', 'textBaseAlign', 'shadow', 'lineWidth',
'lineCap', 'lineJoin', 'lineDash', 'miterLimit', 'fontSize'];
styles.forEach((style) => {
Object.defineProperty(ctx, style, {
set: (value) => {
if ((style !== 'fillStyle' && style !== 'strokeStyle')
|| (value !== 'none' && value !== null)
) {
ctx[`set${style.charAt(0).toUpperCase()}${style.slice(1)}`](value);
}
},
});
});
ctx.createRadialGradient = () => ctx.createCircularGradient(arguments);
}
initEvent() {
this.event = {};
const eventNames = [{
wxName: 'touchStart',
ecName: 'mousedown',
}, {
wxName: 'touchMove',
ecName: 'mousemove',
}, {
wxName: 'touchEnd',
ecName: 'mouseup',
}, {
wxName: 'touchEnd',
ecName: 'click',
}];
eventNames.forEach((name) => {
this.event[name.wxName] = (e) => {
const touch = e.mp.touches[0];
this.chart._zr.handler.dispatch(name.ecName, {
zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
zrY: name.wxName === 'tap' ? touch.clientY : touch.y,
});
};
});
}
}

484
src/components/mpvue-picker/mpvuePicker.vue

@ -0,0 +1,484 @@
<template>
<view class="mpvue-picker">
<view :class="{'pickerMask':showPicker}" @click="maskClick" catchtouchmove="true"></view>
<view class="mpvue-picker-content " :class="{'mpvue-picker-view-show':showPicker}">
<view class="mpvue-picker__hd" catchtouchmove="true">
<view class="mpvue-picker__action" @click="pickerCancel">取消</view>
<view class="mpvue-picker__action" :style="{color:themeColor}" @click="pickerConfirm">确定</view>
</view>
<!-- 单列 -->
<picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue"
@change="pickerChange" v-if="mode==='selector' && pickerValueSingleArray.length > 0">
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueSingleArray" :key="index">{{item.label}}
</view>
</picker-view-column>
</picker-view>
<!-- 时间选择器 -->
<picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue"
@change="pickerChange" v-if="mode==='timeSelector'">
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueHour" :key="index">{{item.label}}</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueMinute" :key="index">{{item.label}}
</view>
</picker-view-column>
</picker-view>
<!-- 多列选择 -->
<picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue"
@change="pickerChange" v-if="mode==='multiSelector'">
<!-- #ifdef VUE3 -->
<template v-for="(n,index) in pickerValueMulArray.length" :key="index">
<picker-view-column>
<view class="picker-item" v-for="(item,index1) in pickerValueMulArray[n]" :key="index1">
{{item.label}}
</view>
</picker-view-column>
</template>
<!-- #endif -->
<!-- #ifndef VUE3 -->
<block v-for="(n,index) in pickerValueMulArray.length" :key="index">
<picker-view-column>
<view class="picker-item" v-for="(item,index1) in pickerValueMulArray[n]" :key="index1">
{{item.label}}
</view>
</picker-view-column>
</block>
<!-- #endif -->
</picker-view>
<!-- 二级联动 -->
<picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue"
@change="pickerChangeMul" v-if="mode==='multiLinkageSelector' && deepLength===2">
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueMulTwoOne" :key="index">{{item.label}}
</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueMulTwoTwo" :key="index">{{item.label}}
</view>
</picker-view-column>
</picker-view>
<!-- 三级联动 -->
<picker-view indicator-style="height: 40px;" class="mpvue-picker-view" :value="pickerValue"
@change="pickerChangeMul" v-if="mode==='multiLinkageSelector' && deepLength===3">
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueMulThreeOne" :key="index">{{item.label}}
</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueMulThreeTwo" :key="index">{{item.label}}
</view>
</picker-view-column>
<picker-view-column>
<view class="picker-item" v-for="(item,index) in pickerValueMulThreeThree" :key="index">
{{item.label}}
</view>
</picker-view-column>
</picker-view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
pickerChangeValue: [],
pickerValue: [],
pickerValueArrayChange: true,
modeChange: false,
pickerValueSingleArray: [],
pickerValueHour: [],
pickerValueMinute: [],
pickerValueMulArray: [],
pickerValueMulTwoOne: [],
pickerValueMulTwoTwo: [],
pickerValueMulThreeOne: [],
pickerValueMulThreeTwo: [],
pickerValueMulThreeThree: [],
/* 是否显示控件 */
showPicker: false,
};
},
props: {
/* mode */
mode: {
type: String,
default: 'selector'
},
/* picker 数值 */
pickerValueArray: {
type: Array,
default () {
return []
}
},
/* 默认值 */
pickerValueDefault: {
type: Array,
default () {
return []
}
},
/* 几级联动 */
deepLength: {
type: Number,
default: 2
},
/* 主题色 */
themeColor: String
},
watch: {
pickerValueArray(oldVal, newVal) {
this.pickerValueArrayChange = true;
},
mode(oldVal, newVal) {
this.modeChange = true;
},
pickerValueArray(val) {
this.initPicker(val);
}
},
methods: {
initPicker(valueArray) {
let pickerValueArray = valueArray;
this.pickerValue = this.pickerValueDefault;
//
if (this.mode === 'selector') {
this.pickerValueSingleArray = valueArray;
} else if (this.mode === 'timeSelector') {
this.modeChange = false;
let hourArray = [];
let minuteArray = [];
for (let i = 0; i < 24; i++) {
hourArray.push({
value: i,
label: i > 9 ? `${i}` : `0${i}`
});
}
for (let i = 0; i < 60; i++) {
minuteArray.push({
value: i,
label: i > 9 ? `${i}` : `0${i}`
});
}
this.pickerValueHour = hourArray;
this.pickerValueMinute = minuteArray;
} else if (this.mode === 'multiSelector') {
this.pickerValueMulArray = valueArray;
} else if (this.mode === 'multiLinkageSelector' && this.deepLength === 2) {
//
let pickerValueMulTwoOne = [];
let pickerValueMulTwoTwo = [];
//
for (let i = 0, length = pickerValueArray.length; i < length; i++) {
pickerValueMulTwoOne.push(pickerValueArray[i]);
}
//
//
if (this.pickerValueDefault.length === 2) {
let num = this.pickerValueDefault[0];
for (
let i = 0, length = pickerValueArray[num].children.length; i < length; i++
) {
pickerValueMulTwoTwo.push(pickerValueArray[num].children[i]);
}
} else {
for (
let i = 0, length = pickerValueArray[0].children.length; i < length; i++
) {
pickerValueMulTwoTwo.push(pickerValueArray[0].children[i]);
}
}
this.pickerValueMulTwoOne = pickerValueMulTwoOne;
this.pickerValueMulTwoTwo = pickerValueMulTwoTwo;
} else if (
this.mode === 'multiLinkageSelector' &&
this.deepLength === 3
) {
let pickerValueMulThreeOne = [];
let pickerValueMulThreeTwo = [];
let pickerValueMulThreeThree = [];
//
for (let i = 0, length = pickerValueArray.length; i < length; i++) {
pickerValueMulThreeOne.push(pickerValueArray[i]);
}
//
this.pickerValueDefault =
this.pickerValueDefault.length === 3 ?
this.pickerValueDefault : [0, 0, 0];
if (this.pickerValueDefault.length === 3) {
let num = this.pickerValueDefault[0];
for (
let i = 0, length = pickerValueArray[num].children.length; i < length; i++
) {
pickerValueMulThreeTwo.push(pickerValueArray[num].children[i]);
}
//
let numSecond = this.pickerValueDefault[1];
for (let i = 0, length = pickerValueArray[num].children[numSecond].children.length; i <
length; i++) {
pickerValueMulThreeThree.push(
pickerValueArray[num].children[numSecond].children[i]
);
}
}
this.pickerValueMulThreeOne = pickerValueMulThreeOne;
this.pickerValueMulThreeTwo = pickerValueMulThreeTwo;
this.pickerValueMulThreeThree = pickerValueMulThreeThree;
}
},
show() {
setTimeout(() => {
if (this.pickerValueArrayChange || this.modeChange) {
this.initPicker(this.pickerValueArray);
this.showPicker = true;
this.pickerValueArrayChange = false;
this.modeChange = false;
} else {
this.showPicker = true;
}
}, 0);
},
maskClick() {
this.pickerCancel();
},
pickerCancel() {
this.showPicker = false;
this._initPickerVale();
let pickObj = {
index: this.pickerValue,
value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
};
this.$emit('onCancel', pickObj);
},
pickerConfirm(e) {
this.showPicker = false;
this._initPickerVale();
let pickObj = {
index: this.pickerValue,
value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
};
this.$emit('onConfirm', pickObj);
},
showPickerView() {
this.showPicker = true;
},
pickerChange(e) {
console.log(11111111, e);
this.pickerValue = e.detail.value;
let pickObj = {
index: this.pickerValue,
value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
};
this.$emit('onChange', pickObj);
},
pickerChangeMul(e) {
if (this.deepLength === 2) {
let pickerValueArray = this.pickerValueArray;
let changeValue = e.detail.value;
//
if (changeValue[0] !== this.pickerValue[0]) {
let pickerValueMulTwoTwo = [];
//
for (let i = 0, length = pickerValueArray[changeValue[0]].children.length; i < length; i++) {
pickerValueMulTwoTwo.push(pickerValueArray[changeValue[0]].children[i]);
}
this.pickerValueMulTwoTwo = pickerValueMulTwoTwo;
// 0
changeValue[1] = 0;
}
this.pickerValue = changeValue;
} else if (this.deepLength === 3) {
let pickerValueArray = this.pickerValueArray;
let changeValue = e.detail.value;
let pickerValueMulThreeTwo = [];
let pickerValueMulThreeThree = [];
//
//
if (changeValue[0] !== this.pickerValue[0]) {
this.pickerValueMulThreeTwo = [];
for (let i = 0, length = pickerValueArray[changeValue[0]].children.length; i < length; i++) {
pickerValueMulThreeTwo.push(pickerValueArray[changeValue[0]].children[i]);
}
//
for (let i = 0, length = pickerValueArray[changeValue[0]].children[0].children.length; i <
length; i++) {
pickerValueMulThreeThree.push(pickerValueArray[changeValue[0]].children[0].children[i]);
}
changeValue[1] = 0;
changeValue[2] = 0;
this.pickerValueMulThreeTwo = pickerValueMulThreeTwo;
this.pickerValueMulThreeThree = pickerValueMulThreeThree;
} else if (changeValue[1] !== this.pickerValue[1]) {
//
//
this.pickerValueMulThreeThree = [];
pickerValueMulThreeTwo = this.pickerValueMulThreeTwo;
for (let i = 0, length = pickerValueArray[changeValue[0]].children[changeValue[1]].children
.length; i <
length; i++) {
pickerValueMulThreeThree.push(pickerValueArray[changeValue[0]].children[changeValue[1]]
.children[
i]);
}
changeValue[2] = 0;
this.pickerValueMulThreeThree = pickerValueMulThreeThree;
}
this.pickerValue = changeValue;
}
let pickObj = {
index: this.pickerValue,
value: this._getPickerLabelAndValue(this.pickerValue, this.mode).value,
label: this._getPickerLabelAndValue(this.pickerValue, this.mode).label
};
this.$emit('onChange', pickObj);
},
// pxikerLabel
_getPickerLabelAndValue(value, mode) {
let pickerLable;
let pickerGetValue = [];
// selector
if (mode === 'selector') {
pickerLable = this.pickerValueSingleArray[value].label;
pickerGetValue.push(this.pickerValueSingleArray[value].value);
} else if (mode === 'timeSelector') {
pickerLable = `${this.pickerValueHour[value[0]].label}-${this.pickerValueMinute[value[1]].label}`;
pickerGetValue.push(this.pickerValueHour[value[0]].value);
pickerGetValue.push(this.pickerValueHour[value[1]].value);
} else if (mode === 'multiSelector') {
for (let i = 0; i < value.length; i++) {
if (i > 0) {
pickerLable += this.pickerValueMulArray[i][value[i]].label + (i === value.length - 1 ? '' :
'-');
} else {
pickerLable = this.pickerValueMulArray[i][value[i]].label + '-';
}
pickerGetValue.push(this.pickerValueMulArray[i][value[i]].value);
}
} else if (mode === 'multiLinkageSelector') {
/* eslint-disable indent */
pickerLable =
this.deepLength === 2 ?
`${this.pickerValueMulTwoOne[value[0]].label}-${this.pickerValueMulTwoTwo[value[1]].label}` :
`${this.pickerValueMulThreeOne[value[0]].label}-${this.pickerValueMulThreeTwo[value[1]].label}-${this.pickerValueMulThreeThree[value[2]].label}`;
if (this.deepLength === 2) {
pickerGetValue.push(this.pickerValueMulTwoOne[value[0]].value);
pickerGetValue.push(this.pickerValueMulTwoTwo[value[1]].value);
} else {
pickerGetValue.push(this.pickerValueMulThreeOne[value[0]].value);
pickerGetValue.push(this.pickerValueMulThreeTwo[value[1]].value);
pickerGetValue.push(this.pickerValueMulThreeThree[value[2]].value);
}
/* eslint-enable indent */
}
return {
label: pickerLable,
value: pickerGetValue
};
},
// pickerValue
_initPickerVale() {
if (this.pickerValue.length === 0) {
if (this.mode === 'selector') {
this.pickerValue = [0];
} else if (this.mode === 'multiSelector') {
this.pickerValue = new Int8Array(this.pickerValueArray.length);
} else if (
this.mode === 'multiLinkageSelector' &&
this.deepLength === 2
) {
this.pickerValue = [0, 0];
} else if (
this.mode === 'multiLinkageSelector' &&
this.deepLength === 3
) {
this.pickerValue = [0, 0, 0];
}
}
}
}
};
</script>
<style>
.pickerMask {
position: fixed;
z-index: 1000;
top: 0;
right: 0;
left: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.6);
}
.mpvue-picker-content {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
transition: all 0.3s ease;
transform: translateY(100%);
z-index: 3000;
}
.mpvue-picker-view-show {
transform: translateY(0);
}
.mpvue-picker__hd {
display: flex;
padding: 9px 15px;
background-color: #fff;
position: relative;
text-align: center;
font-size: 17px;
}
.mpvue-picker__hd:after {
content: ' ';
position: absolute;
left: 0;
bottom: 0;
right: 0;
height: 1px;
border-bottom: 1px solid #e5e5e5;
color: #e5e5e5;
transform-origin: 0 100%;
transform: scaleY(0.5);
}
.mpvue-picker__action {
display: block;
flex: 1;
color: #1aad19;
}
.mpvue-picker__action:first-child {
text-align: left;
color: #888;
}
.mpvue-picker__action:last-child {
text-align: right;
}
.picker-item {
text-align: center;
line-height: 40px;
font-size: 16px;
}
.mpvue-picker-view {
position: relative;
bottom: 0;
left: 0;
width: 100%;
height: 238px;
background-color: rgba(255, 255, 255, 1);
}
</style>

175
src/components/mpvueGestureLock/gestureLock.js

@ -0,0 +1,175 @@
class GestureLock {
constructor(containerWidth, cycleRadius) {
this.containerWidth = containerWidth; // 容器宽度
this.cycleRadius = cycleRadius; // 圆的半径
this.circleArray = []; // 全部圆的对象数组
this.checkPoints = []; // 选中的圆的对象数组
this.lineArray = []; // 已激活锁之间的线段数组
this.lastCheckPoint = 0; // 最后一个激活的锁
this.offsetX = 0; // 容器的 X 偏移
this.offsetY = 0; // 容器的 Y 偏移
this.activeLine = {}; // 最后一个激活的锁与当前位置之间的线段
this.windowWidth = wx.getSystemInfoSync().windowWidth; // 窗口大小(用于rpx 和 px 转换)
this.initCircleArray();
}
// 初始化 画布上的 9个圆
initCircleArray() {
const cycleMargin = (this.containerWidth - 6 * this.cycleRadius) / 6;
let count = 0;
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
count++;
this.circleArray.push({
count: count,
x: this.rpxTopx((cycleMargin + this.cycleRadius) * (j * 2 + 1)),
y: this.rpxTopx((cycleMargin + this.cycleRadius) * (i * 2 + 1)),
radius: this.rpxTopx(this.cycleRadius),
check: false,
style: {
left: (cycleMargin + this.cycleRadius) * (j * 2 + 1) - this.cycleRadius + 'rpx',
top: (cycleMargin + this.cycleRadius) * (i * 2 + 1) - this.cycleRadius + 'rpx',
width: this.cycleRadius * 2 + 'rpx',
}
});
}
}
}
onTouchStart(e) {
this.setOffset(e);
this.checkTouch({
x: e.touches[0].pageX - this.offsetX,
y: e.touches[0].pageY - this.offsetY
});
}
onTouchMove(e) {
this.moveDraw(e)
}
onTouchEnd(e) {
const checkPoints = this.checkPoints;
this.reset();
return checkPoints;
}
// 初始化 偏移量
setOffset(e) {
this.offsetX = e.currentTarget.offsetLeft;
this.offsetY = e.currentTarget.offsetTop;
}
// 检测当时 触摸位置是否位于 锁上
checkTouch({
x,
y
}) {
for (let i = 0; i < this.circleArray.length; i++) {
let point = this.circleArray[i];
if (this.isPointInCycle(x, y, point.x, point.y, point.radius)) {
if (!point.check) {
this.checkPoints.push(point.count);
if (this.lastCheckPoint != 0) {
// 已激活锁之间的线段
const line = this.drawLine(this.lastCheckPoint, point);
this.lineArray.push(line);
}
this.lastCheckPoint = point;
}
point.check = true;
return;
}
}
}
// 画线 - 返回 样式 对象
drawLine(start, end) {
const width = this.getPointDis(start.x, start.y, end.x, end.y);
const rotate = this.getAngle(start, end);
return {
activeLeft: start.x + 'px',
activeTop: start.y + 'px',
activeWidth: width + 'px',
activeRotate: rotate + 'deg'
}
}
// 获取 画线的 角度
getAngle(start, end) {
var diff_x = end.x - start.x,
diff_y = end.y - start.y;
if (diff_x >= 0) {
return 360 * Math.atan(diff_y / diff_x) / (2 * Math.PI);
} else {
return 180 + 360 * Math.atan(diff_y / diff_x) / (2 * Math.PI);
}
}
// 判断 当前点是否位于 锁内
isPointInCycle(x, y, circleX, circleY, radius) {
return (this.getPointDis(x, y, circleX, circleY) < radius) ? true : false;
}
// 获取两点之间距离
getPointDis(ax, ay, bx, by) {
return Math.sqrt(Math.pow(ax - bx, 2) + Math.pow(ay - by, 2));
}
// 移动 绘制
moveDraw(e) {
// 画经过的圆
const x = e.touches[0].pageX - this.offsetX;
const y = e.touches[0].pageY - this.offsetY;
this.checkTouch({
x,
y
});
// 画 最后一个激活的锁与当前位置之间的线段
this.activeLine = this.drawLine(this.lastCheckPoint, {
x,
y
});
}
// 使 画布 恢复初始状态
reset() {
this.circleArray.forEach((item) => {
item.check = false;
});
this.checkPoints = [];
this.lineArray = [];
this.activeLine = {};
this.lastCheckPoint = 0;
}
// 获取 最后一个激活的锁与当前位置之间的线段
getActiveLine() {
return this.activeLine;
}
// 获取 圆对象数组
getCycleArray() {
return this.circleArray;
}
// 获取 已激活锁之间的线段
getLineArray() {
return this.lineArray;
}
// 将 RPX 转换成 PX
rpxTopx(rpx) {
return rpx / 750 * this.windowWidth;
}
}
export default GestureLock;

138
src/components/mpvueGestureLock/index.vue

@ -0,0 +1,138 @@
<template>
<view class="gesture-lock" :class="{error:error}" :style="{width: containerWidth +'rpx', height:containerWidth +'rpx'}"
@touchstart.stop="onTouchStart" @touchmove.stop="onTouchMove" @touchend.stop="onTouchEnd">
<!-- 同级 v-for key 重复会有问题需要套一层 -->
<!-- 9 个圆 -->
<view>
<view v-for="(item,i) in circleArray" :key="i" class="cycle" :class="{check:item.check}" :style="{left:item.style.left,top:item.style.top,width:item.style.width,height:item.style.width}">
</view>
</view>
<view>
<!-- 已激活锁之间的线段 -->
<view v-for="(item,i) in lineArray" :key="i" class="line" :style="{left:item.activeLeft,top:item.activeTop,width:item.activeWidth,'-webkit-transform':'rotate('+item.activeRotate+')',transform:'rotate('+item.activeRotate+')'}">
</view>
</view>
<!-- 最后一个激活的锁与当前位置之间的线段 -->
<view class="line" :style="{left:activeLine.activeLeft,top:activeLine.activeTop,width:activeLine.activeWidth,'-webkit-transform':'rotate('+activeLine.activeRotate+')',transform:'rotate('+activeLine.activeRotate+')'}">
</view>
</view>
</template>
<script>
import GestureLock from './gestureLock';
export default {
name: 'index',
props: {
/**
* 容器宽度
*/
containerWidth: {
type: [Number, String],
default: 0
},
/**
* 圆的半径
*/
cycleRadius: {
type: [Number, String],
default: 0
},
/**
* 已设定的密码
*/
password: {
type: Array,
default () {
return []
}
},
},
data() {
return {
gestureLock: {}, //
circleArray: [], //
lineArray: [], // 线
activeLine: {}, // 线
error: false
}
},
methods: {
onTouchStart(e) {
this.gestureLock.onTouchStart(e);
this.refesh();
},
onTouchMove(e) {
this.gestureLock.onTouchMove(e);
this.refesh();
},
onTouchEnd(e) {
const checkPoints = this.gestureLock.onTouchEnd(e);
if (!this.password.length || checkPoints.join('') == this.password.join('')) {
this.refesh();
this.$emit('end', checkPoints);
} else {
this.error = true;
setTimeout(() => {
this.refesh();
this.$emit('end', checkPoints);
}, 800);
}
},
refesh() {
this.error = false;
this.circleArray = this.gestureLock.getCycleArray();
this.lineArray = this.gestureLock.getLineArray();
this.activeLine = this.gestureLock.getActiveLine();
}
},
mounted() {
this.gestureLock = new GestureLock(this.containerWidth, this.cycleRadius);
this.refesh();
}
}
</script>
<style scoped>
.gesture-lock {
margin: 0 auto;
position: relative;
box-sizing: border-box;
overflow: auto;
}
.gesture-lock .cycle {
box-sizing: border-box;
position: absolute;
border: 2px solid #66aaff;
border-radius: 50%;
}
.gesture-lock .cycle.check:after {
content: "";
display: block;
position: absolute;
width: 32%;
height: 32%;
border: 2px solid #66aaff;
border-radius: 50%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.gesture-lock .line {
height: 0;
border-top: 2px solid #66aaff;
position: absolute;
transform-origin: left center;
}
.gesture-lock.error .cycle.check,
.gesture-lock.error .cycle.check:after,
.gesture-lock.error .line {
border-color: #ffa197;
}
</style>

157
src/components/my-paging/my-paging.vue

@ -0,0 +1,157 @@
<!-- 基于z-paging封装个性化分页组件演示可减少大量重复代码 -->
<template>
<!-- 这边统一设置z-paging在页面中使用时就不用重复写 -->
<!-- 如果要在这里设置极简写法这里的ref不能设置为paging设置为其他名即可因为极简写法会修改/调用第一个包含了ref="paging"的付view中的list和query -->
<!-- 极简写法在下方设置autowire-list-name="xxx" autowire-query-name="xxx"即可与minimalism-demo.vue中的一致并且不用再从这个组件转发到页面只要遵循上一行的规则即可 -->
<z-paging ref="paging" v-model="list" fixed auto-show-back-to-top refresher-threshold="160rpx" @query="queryList"
:useVirtualList="useVirtualList" :useInnerList="useInnerList" :cellKeyName="cellKeyName" :innerListStyle="innerListStyle" :preloadPage="preloadPage" :cellHeightMode="cellHeightMode" :virtualScrollFps="virtualScrollFps"
:loading-more-loading-text="{'en':'英文的加载中','zh-cn':'中文的加载中','zh-hant-cn':'繁体的加载中'}">
<!-- 这里插入一个view到z-paging中并且这个view会被z-paging标记为top固定在顶部 -->
<template #top>
<!-- 这里接收页面传进来的slot这样相当于将页面传进来的slot传给z-paging的slot="top" -->
<slot name="top" />
</template>
<!-- 这里插入一个view到z-paging中并且这个view会被z-paging标记为bottom固定在顶部 -->
<!-- vue3中用v-slot:bottom -->
<template #bottom>
<!-- 这里接收页面传进来的slot这样相当于将页面传进来的slot传给z-paging的slot="bottom" -->
<slot name="bottom" />
</template>
<template #empty v-if="$slots.empty" >
<!-- 这里接收页面传进来的slot这样相当于将页面传进来的slot传给z-paging的slot="empty" -->
<slot name="empty" />
</template>
<!-- 这个是插入虚拟列表/内置列表的cell -->
<template #cell="{item,index}">
<slot name="cell" :item="item" :index="index"/>
</template>
<!-- 这里通过slot统一自定义了下拉刷新view和没有更多数据view页面那边就不用再写下面两行了 -->
<!-- 自定义下拉刷新view(如果use-custom-refresher为true且不设置下面的slot="refresher"此时不用获取refresherStatus会自动使用z-paging自带的下拉刷新view) -->
<template #refresher="{refresherStatus}">
<!-- <custom-refresher :status="refresherStatus" /> -->
</template>
<!-- 自定义没有更多数据view -->
<template #loadingMoreNoMore>
<!-- <custom-nomore></custom-nomore> -->
<uni-load-more status="normore" />
</template>
<!-- 这里接收页面传进来的普通slot如列表数据等 -->
<slot />
</z-paging>
</template>
<script>
export default {
name: "my-paging",
data() {
return {
list: []
};
},
props: {
//v-modellist
value: {
type: Array,
default: function() {
return [];
}
},
//使
useVirtualList: {
type: Boolean,
default: false
},
//z-paging()use-virtual-listtruetrue
useInnerList: {
type: Boolean,
default: false
},
//cellkeynvuenvueuse-inner-list
cellKeyName: {
type: String,
default: ''
},
//innerList
innerListStyle: {
type: Object,
default: function() {
return {};
}
},
//()127celldom()
preloadPage: {
type: [Number, String],
default: 12
},
//cellfixedcellcelldynamicdynamicfixed
cellHeightMode: {
type: String,
default: 'fixed'
},
//scroll60
virtualScrollFps: {
type: [Number, String],
default: 60
},
},
watch: {
//v-modez-paging
value(newVal) {
this.list = newVal;
},
// #ifdef VUE3
modelValue(newVal) {
this.list = newVal;
},
// #endif
//z-paging
list(newVal) {
//emit inputv-model
this.$emit('input', newVal);
// #ifdef VUE3
this.$emit('update:modelValue', newVal);
// #endif
}
},
methods: {
//z-paging@queryemit
queryList(pageNo, pageSize) {
console.log("queryList",pageNo)
// this.$emit('query', pageNo, pageSize);
},
//reloadz-paging
reload(data) {
this.$refs.paging.reload(data);
},
//completez-paging
complete(data) {
this.$refs.paging.complete(data);
},
/*
//使mixins使
//updatePageScrollTopz-paging
updatePageScrollTop(data){
this.$refs.paging.updatePageScrollTop(data);
},
//pageReachBottomz-paging
pageReachBottom(){
this.$refs.paging.pageReachBottom();
},
//doChatRecordLoadMorez-paging
doChatRecordLoadMore() {
this.$refs.paging.doChatRecordLoadMore();
}
*/
}
}
</script>
<style>
</style>

38
src/components/page-foot/page-foot.vue

@ -0,0 +1,38 @@
<template name="page-foot">
<view class="page-share-title">
<text>感谢{{name}}提供本示例</text>
<text class="submit" @click="submit">我也提交</text>
</view>
</template>
<script>
export default {
name: "page-foot",
props: {
name: {
type: String,
default: ""
}
},
methods: {
submit() {
uni.showModal({
content:"hello uni-app开源地址为https://github.com/dcloudio/uni-app/tree/master/examples,请在这个开源项目上贡献你的代码",
showCancel:false
})
}
}
}
</script>
<style>
.page-share-title {
text-align: center;
font-size: 30rpx;
color: #BEBEBE;
padding: 20rpx 0;
}
.submit {
border-bottom: 1rpx solid #BEBEBE;
}
</style>

16
src/components/page-head/page-head.vue

@ -0,0 +1,16 @@
<template name="page-head">
<view class="common-page-head">
<view class="common-page-head-title">{{title}}</view>
</view>
</template>
<script>
export default {
name: "page-head",
props: {
title: {
type: String,
default: ""
}
}
}
</script>

663
src/components/pullDown/pullDown.vue

@ -0,0 +1,663 @@
<template>
<view>
<view class="maskbox" v-show="active" @tap="maskClick"></view>
<view :class="description == 'row'?'uni-combox-row':'uni-combox-column'">
<view v-if="label" class="uni-combox__label" :style="labelStyle">
<text>{{label}}</text>
</view>
<view class="u-dropdown">
<view class="u-dropdown__menu">
<view class="u-dropdown__menu__item">
<view class="u-flex " style="width: 100%;">
<view class="u-close-wrap" v-if="isSearch">
<u-icon class="u-clear-icon" :size="30" :name="searchIcon"
:color="searchIconColor ? searchIconColor : color"></u-icon>
</view>
<view class="u-input">
<u-input confirm-type="search" class="uni-combox__input"
:type="isAutoHeight ? 'textarea':'text'" v-model="inputVal" @confirm="confirm()"
:placeholder="placeholder" :auto-height="isAutoHeight"
:height="isAutoHeight ?height-20:height" />
</view>
<icon class="uni-combox__icon" type="clear" size="16" @tap="clearInputValue"
v-if="inputVal!=''" style="height: 100%;align-items: center;justify-content: center;" />
<!-- <image size="16" src="/static/icons/close-circle2.svg"
style="height: 35%;width: 10%;align-items: center;justify-content: center;background-color: aqua;display: flex;"> -->
<!-- </image> -->
<view :style="{width:height + 'rpx'}" class="u-dropdown__menu__item__arrow" :class="{
'u-dropdown__menu__item__arrow--rotate': active
}" @tap.stop="menuClick()">
<u-icon :custom-style="{display: 'flex'}" :name="menuIcon"
:size="$u.addUnit(menuIconSize)" :color="active ? activeColor : '#c0c4cc'"></u-icon>
</view>
</view>
</view>
</view>
<view class="u-dropdown__content" :style="[contentStyle, {
transition: `opacity ${duration / 1000}s linear`,
top: $u.addUnit(height+28),
height: contentHeight + 'px'}]" @tap="maskClick" @touchmove.stop.prevent>
<view class="u-dropdown__content__popup" :style="[popupStyle]" @touchmove.stop.prevent="() => {}"
@tap.stop.prevent="() => {}">
<view class="uni-combox__selector-empty" v-if="optionsLength === 0" @click="empty()">
<text>{{emptyTips}}</text>
</view>
<view v-for="(item, index) in filterOptions" style="width: 100%;"
@click="onSelectorClick(index)">
<view v-if="itemTextCount == 1" class="uni-combox-item">
<text class="uni-combox-item-text" :title-style="{
color: inputVal === item ? activeColor : inactiveColor
}">{{item}}</text>
<u-icon v-if="inputVal === item" name="checkbox-mark" :color="activeColor" size="32">
</u-icon>
</view>
<view v-if="itemTextCount == 2" class="uni-combox-item2">
<text class="uni-combox-item-text" :title-style="{
color: inputVal === item ? activeColor : inactiveColor
}">{{item.value}}</text>
<text class="uni-combox-item-text" :title-style="{
color: inputVal === item ? activeColor : inactiveColor
}">{{item.desc}}</text>
</view>
<u-line class="line_color"></u-line>
</view>
</view>
<!-- <view class="u-dropdown__content__mask"></view> -->
</view>
</view>
</view>
</view>
</template>
<script>
/**
* dropdown 下拉菜单
* @description 菜单标题与编辑框排列方向,即水平排列row/垂直排列column,默认水平排列row
* @tutorial http://uviewui.com/components/dropdown.html
* @property {String} active-color 标题和选项卡选中的颜色默认#2979ff
* @property {String} inactive-color 标题和选项卡未选中的颜色默认#606266
* @property {Boolean} close-on-click-mask 点击遮罩是否关闭菜单默认true
* @property {Boolean} close-on-click-self 点击当前激活项标题是否关闭菜单默认true
* @property {String | Number} duration 选项卡展开和收起的过渡时间单位ms默认300
* @property {String | Number} height 标题菜单的高度单位任意默认80
* @property {String | Number} border-radius 菜单展开内容下方的圆角值单位任意默认0
* @property {Boolean} border-bottom 标题菜单是否显示下边框默认false
* @property {String | Number} title-size 标题的字体大小单位任意数值默认为rpx单位默认28
* @event {Function} open 下拉菜单被打开时触发
* @event {Function} close 下拉菜单被关闭时触发
* @example <pulldown></pulldown>
*/
export default {
name: 'pulldown',
emits: ["open", "close", "update:modelValue", "input", "change", "confirm"],
props: {
// ,row/column
description: {
type: String,
default: 'row'
},
//
label: {
type: String,
default: ''
},
//
labelWidth: {
type: String,
default: 'auto'
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
inactiveColor: {
type: String,
default: '#606266'
},
//
closeOnClickMask: {
type: Boolean,
default: true
},
//
closeOnClickSelf: {
type: Boolean,
default: true
},
//
duration: {
type: [Number, String],
default: 300
},
// rpx
height: {
type: [Number, String],
default: 55
},
//
borderBottom: {
type: Boolean,
default: false
},
//
titleSize: {
type: [Number, String],
default: 28
},
//
borderRadius: {
type: [Number, String],
default: 0
},
// icon
menuIcon: {
type: String,
default: 'arrow-down'
},
//
menuIconSize: {
type: [Number, String],
default: 26
},
emptyTips: {
type: String,
default: '无匹配项'
},
//
isSearch: {
type: Boolean,
default: false
},
//
hint: {
type: String,
default: ''
},
//
searchIconColor: {
type: String,
default: ''
},
//
color: {
type: String,
default: '#606266'
},
// uView
searchIcon: {
type: String,
default: 'search'
},
// slot
options: {
type: Array,
default () {
return [];
}
},
//
itemTextCount: {
type: Number,
default: 1
},
//
isAutoHeight: {
type: Boolean,
default: false
},
},
data() {
return {
inputVal: '',
showDropdown: true, // ,
menuList: [], //
active: false, //
// false""current0
// TX使===使==
current: 99999,
//
contentStyle: {
// zIndex: 11,
zIndex: -1,
opacity: 0
},
//
highlightIndex: 99999,
contentHeight: 0
}
},
computed: {
//
popupStyle() {
let style = {};
// Y100%
style.transform = `translateY(${this.active ? 0 : '-100%'})`
style['transition-duration'] = this.duration / 1000 + 's';
style.borderRadius = `0 0 ${this.$u.addUnit(this.borderRadius)} ${this.$u.addUnit(this.borderRadius)}`;
return style;
},
labelStyle() {
if (this.labelWidth === 'auto') {
return {}
}
return {
width: this.labelWidth
}
},
optionsLength() {
return this.options.length
},
filterOptions() {
if (this.isSearch) {
return this.options.filter((item) => {
return item.indexOf(this.inputVal) > -1
})
} else {
return this.options;
}
},
placeholder() {
if (this.hint) {
return this.hint;
} else {
if (this.isSearch) {
return '请输入关键字';
} else {
return '请选择';
}
}
},
},
created() {
// (u-dropdown-item)thisdata
this.children = [];
},
mounted() {
this.getContentHeight();
},
methods: {
//
clearInputValue() {
this.inputVal = "";
},
//
confirm() {
this.$emit("confirm", this.inputVal);
},
init() {
// init
//
this.menuList = [];
this.children.map(child => {
child.init();
})
},
//
menuClick() {
//
// if (this.menuList[index].disabled) return;
//
if (this.active) {
this.close();
//
// setTimeout(() => {
// this.active = false;
// }, this.duration)
return;
}
this.open();
},
onSelectorClick(index) {
// console.log(index);
if (this.itemTextCount == 1) {
this.inputVal = this.options[index];
this.close();
// v-model
this.$emit("input", this.inputVal);
this.$emit("update:modelValue", this.inputVal);
// value
this.$emit("change", index, this.inputVal);
} else if (this.itemTextCount == 2) {
this.inputVal = this.options[index].value;
this.close();
// v-model
this.$emit("input", this.inputVal);
this.$emit("update:modelValue", this.inputVal);
// value
this.$emit("change", index, this.inputVal);
}
},
//
open() {
console.log(this.options[0]);
console.log(this.options.length);
// console.log(this.filterOptions());
//
// this.highlightIndex = 9999;
//
this.contentStyle = {
zIndex: 11,
}
this.$forceUpdate();
//
this.active = true;
// this.current = index;
// v-if
// display: nonenvuedisplay
this.$emit('open', this.current);
},
//
close() {
this.$emit('close', this.current);
// current
this.active = false;
this.current = 99999;
// 0
this.contentStyle = {
zIndex: -1,
opacity: 0
}
},
//
empty() {
// current
this.active = false;
this.current = 99999;
// 0
this.contentStyle = {
zIndex: -1,
opacity: 0
}
},
//
maskClick() {
//
if (!this.closeOnClickMask) return;
this.close();
},
//
highlight(index = undefined) {
this.highlightIndex = index !== undefined ? index : 99999;
},
//
getContentHeight() {
// dropdown
//
// this.$u.sys()uView
let windowHeight = this.$u.sys().windowHeight;
this.$uGetRect('.u-dropdown__menu').then(res => {
// dropdownH5uniappbug(bughx2.8.11)
// H5bugtop沿bottom
// H5uni
// bottonres.top
this.contentHeight = windowHeight - res.bottom;
// console.log(this.contentHeight);
// console.log(res.bottom);
})
}
}
}
</script>
<style scoped lang="scss">
@import "../../uni_modules/vk-uview-ui/libs/css/style.components.scss";
.u-input {
width: 100%;
padding-top: 5px;
padding-bottom: 5px;
}
.u-clear-icon {
@include vue-flex;
align-items: center;
}
.u-close-wrap {
width: 30px;
height: 100%;
@include vue-flex;
align-items: center;
justify-content: center;
border-radius: 50%;
}
.maskbox {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 4;
}
.uni-combox-row {
/* #ifndef APP-NVUE */
width: 100%;
display: flex;
/* #endif */
min-height: 40px;
flex-direction: row;
align-items: center;
position: relative;
background-color: #FFFFFF;
// padding-right: 5px;
// padding-left: 5px;
// z-index: 3;
}
.uni-combox-column {
/* #ifndef APP-NVUE */
width: 100%;
display: flex;
/* #endif */
min-height: 40px;
flex-direction: column;
align-items: flex-start;
position: relative;
background-color: #FFFFFF;
// padding-right: 5px;
// padding-left: 5px;
// z-index: 3;
}
.uni-combox__label {
font-size: 16px;
line-height: 22px;
padding-right: 10px;
}
.uni-combox__selector-empty,
.uni-combox__selector-item {
/* #ifdef APP-NVUE */
display: flex;
/* #endif */
line-height: 36px;
font-size: 14px;
text-align: center;
border-bottom: solid 1px #DDDDDD;
/* margin: 0px 10px; */
}
.uni-combox__icon {
display: flex;
height: 100%;
align-items: center;
justify-content: center;
background-color: #FFFFFF;
z-index: 4;
}
.uni-combox__input {
// flex: 1;
font-size: 16px;
height: 100%;
line-height: 100%;
background-color: #FFFFFF;
width: 100%;
z-index: 5;
}
.uni-combox-item {
display: flex;
flex-direction: row;
font-size: 16px;
height: 100%;
line-height: 100%;
background-color: #FFFFFF;
width: 100%;
}
.uni-combox-item2 {
display: flex;
flex-direction: column;
font-size: 16px;
height: 100%;
line-height: 100%;
background-color: #FFFFFF;
width: 100%;
}
.uni-combox-item-text {
font-size: 16px;
height: 100%;
line-height: 100%;
background-color: #FFFFFF;
width: 100%;
padding: 20rpx;
display: flex;
}
.uni-combox__input-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
flex-direction: column;
}
.uni-combox__selector {
box-sizing: border-box;
position: absolute;
top: 42px;
left: 0;
width: 100%;
background-color: #FFFFFF;
border-radius: 6px;
box-shadow: #DDDDDD 4px 4px 8px, #DDDDDD -4px -4px 8px;
z-index: 2;
}
.u-dropdown {
flex: 1;
width: 100%;
position: relative;
background-color: #FFFFFF;
margin-right: 2rpx;
margin-left: 2rpx;
&__menu {
@include vue-flex;
// position: relative;
z-index: 11;
width: 100%;
&__item {
// flex: 1;
@include vue-flex;
justify-content: center;
// align-items: center;
border: 2rpx solid $uni-border-color;
width: 100%;
margin-top: 2rpx;
// margin-right: 2rpx;
// margin-left: 2rpx;
&__text {
font-size: 28rpx;
color: $u-content-color;
}
&__arrow {
transition: transform .3s;
align-items: center;
justify-content: center;
@include vue-flex;
&--rotate {
transform: rotate(180deg);
}
}
}
}
&__content {
position: absolute;
z-index: 8;
width: 100%;
left: 0px;
bottom: 0;
overflow: hidden;
// z-index: 10;
// box-sizing: border-box;
// position: absolute;
// top: 42px;
// left: 0;
// width: 100%;
// // background-color: #FFFFFF;
// border-radius: 6px;
// box-shadow: #DDDDDD 4px 4px 8px, #DDDDDD -4px -4px 8px;
// z-index: 10;
&__mask {
position: relative;
z-index: 9;
background: rgba(0, 0, 0, .3);
width: 100%;
height: 100%;
left: 0;
top: 0;
bottom: 0;
}
&__popup {
position: relative;
z-index: 11;
transition: all 0.3s;
transform: translate3D(0, -100%, 0);
overflow: hidden;
width: 100%;
background-color: aliceblue;
border: 2rpx solid $uni-border-color;
// z-index: 10;
}
}
}
</style>

456
src/components/show-modal/show-modal.vue

@ -0,0 +1,456 @@
<template name="show-modal">
<view>
<u-modal v-model="show" :title-style="{color: 'red'}" :title="title" :showTitle="false"
:showConfirmButton="false" ref="modal">
<view class="slot-content">
<slot name="icon">
<image class="icon" :src="icon" />
</slot>
<scroll-view scroll-y="true" style="max-height: 200px;">
<rich-text class="content" :nodes="content">
</rich-text>
</scroll-view>
<u-line></u-line>
<slot name="button">
<view class="uni-flex uni-row u-col-center space-between" style="width: 100%;height: 48px;">
<view v-if="showCancelButton" class="cance_button" @tap="$u.throttle(cancelClose, 500)">
<text :style="{'color':cancelColor}">{{ cancelText }}</text>
</view>
<u-line direction="col" length="100%"></u-line>
<view v-if="showConfirmButton" class="confirm_button" @tap="$u.throttle(confirmClose, 500)">
<text :style="{'color':confirmColor}">{{confirmText}}</text>
<text v-if="showConfirmCountdown">({{seconds}}s关闭)</text>
</view>
</view>
</slot>
</view>
</u-modal>
</view>
</template>
<script>
/**
* modal 模态框
* @description 弹出模态框常用于消息提示消息确认在当前页面内完成特定的交互操作
* */
export default {
data() {
return {
timer: null,
show: false, //
iconType: '消息',
icon: '../../static/icons/error-circle.svg',
title: '', //
content: '', //
cancelText: '取消', //
confirmText: '确定', //
showCancel: true, // true
confirmColor: '#007aff', //
cancelColor: null, //
showConfirmButton: true, //
showConfirmCountdown: true, //
showCancelButton: true, //
showClose: false,
confirm: false, // true
cancel: false, // true
seconds: 0,
success: () => {} //
}
},
methods: {
open() {
this.show = true;
},
close() {
this.$.refs.modal.popupClose();
},
confirmClose() {
if (this.show) {
this.show = false;
clearInterval(this.timer) //timer
this.$.refs.modal.popupClose();
this.success({
// cancel: false,
confirm: true,
});
}
},
cancelClose() {
clearInterval(this.timer) //timer
this.$.refs.modal.popupClose();
this.success({
// cancel: true,
confirm: false,
});
},
// (
showConfirmMessageModal(mContent, callback) {
this.showConfirmModal("消息", mContent, callback);
},
// (
showConfirmSuccessModal(mContent, callback) {
this.showConfirmModal("成功", mContent, callback);
},
// (
showConfirmFailModal(mContent, callback) {
this.showConfirmModal("失败", mContent, callback);
},
// (
showConfirmWarningModal(mContent, callback) {
this.showConfirmModal("警告", mContent, callback);
},
// (
showConfirmQuestionModal(mContent, callback) {
this.showConfirmModal("疑问", mContent, callback);
},
// (
showConfirmModal(mIconType, mContent, callback) {
this.showModal({
iconType: mIconType,
content: mContent,
showCancelButton: false,
success: function(res) {
if (callback != undefined) {
if (res.confirm == true) {
callback(true);
console.log('用户点击确定')
} else {
callback(false);
console.log('用户点击取消')
}
}
}
});
},
// (+
showSelectMessageModal(mContent, callback) {
this.showSelectModal("消息", mContent, callback);
},
// (+
showSelectSuccessModal(mContent, callback) {
this.showSelectModal("成功", mContent, callback);
},
// (+
showSelectFailModal(mContent, callback) {
this.showSelectModal("失败", mContent, callback);
},
// (+
showSelectWarningModal(mContent, callback) {
this.showSelectModal("警告", mContent, callback);
},
// (+
showSelectQuestionModal(mContent, callback) {
this.showSelectModal("疑问", mContent, callback);
},
// (+
showSelectModal(mIconType, mContent, callback) {
this.showModal({
iconType: mIconType,
content: mContent,
success: function(res) {
if (callback != undefined) {
if (res.confirm == true) {
callback(true);
console.log('用户点击确定')
} else {
callback(false);
console.log('用户点击取消')
}
}
}
});
},
// (+)
showConfirmCountdownMessageModal(mContent, callback) {
this.showConfirmCountdownModal("消息", mContent, callback);
},
// (+)
showConfirmCountdownSuccessModal(mContent, callback) {
this.showConfirmCountdownModal("成功", mContent, callback);
},
// (+)
showConfirmCountdownFailModal(mContent, callback) {
this.showConfirmCountdownModal("失败", mContent, callback);
},
// (+)
showConfirmCountdownWarningModal(mContent, callback) {
this.showConfirmCountdownModal("警告", mContent, callback);
},
// (+)
showConfirmCountdownQuestionModal(mContent, callback) {
this.showConfirmCountdownModal("疑问", mContent, callback);
},
// (+)
showConfirmCountdownModal(mIconType, mContent, callback) {
this.showModal({
iconType: mIconType,
content: mContent,
showCancelButton: false,
showConfirmCountdown: true,
success: function(res) {
if (callback != undefined) {
if (res.confirm == true) {
callback(true);
console.log('用户点击确定')
} else {
callback(false);
console.log('用户点击取消')
}
}
}
});
},
// (++)
showSelectCountdownMessageModal(mContent, callback) {
this.showSelectCountdownModal("消息", mContent, callback);
},
// (++)
showSelectCountdownSuccessModal(mContent, callback) {
this.showSelectCountdownModal("成功", mContent, callback);
},
// (++)
showSelectCountdownFailModal(mContent, callback) {
this.showSelectCountdownModal("失败", mContent, callback);
},
// (++)
showSelectCountdownWarningModal(mContent, callback) {
this.showSelectCountdownModal("警告", mContent, callback);
},
// (++)
showSelectCountdownQuestionModal(mContent, callback) {
this.showSelectCountdownModal("疑问", mContent, callback);
},
// (++)
showSelectCountdownModal(mIconType, mContent, callback) {
this.showModal({
iconType: mIconType,
content: mContent,
showConfirmCountdown: true,
success: function(res) {
if (callback != undefined) {
if (res.confirm == true) {
callback(true);
console.log('用户点击确定')
} else {
callback(false);
console.log('用户点击取消')
}
}
}
});
},
//
showModal(data) {
if (data.iconType) {
this.iconType = data.iconType
switch (data.iconType) {
case '消息':
this.icon = '/static/icons/error-circle.svg';
break;
case '成功':
this.icon = '/static/icons/checkmark-circle.svg';
break;
case '失败':
this.icon = '/static/icons/close-circle.svg';
break;
case '警告':
this.icon = '/static/icons/warning.svg';
break;
case '疑问':
this.icon = '/static/icons/question-circle.svg';
break;
default:
break;
}
}
// image
if (data.title) {
this.title = data.title
}
if (data.content) {
console.log(data.content);
this.content = data.content;
} else {
this.content = ''
}
if (data.cancelText) {
this.cancelText = data.cancelText
} else {
this.cancelText = '取消'
}
if (data.confirmText) {
this.confirmText = data.confirmText
} else {
this.confirmText = '确定'
}
if (data.showCancel === false || data.showCancel === true) {
this.showCancel = data.showCancel
} else {
this.showCancel = true
}
if (data.confirmColor) {
this.confirmColor = data.confirmColor
} else {
this.confirmColor = '#007aff'
}
if (data.cancelColor) {
this.cancelColor = data.cancelColor
} else {
this.cancelColor = '#666F83'
}
if (data.showConfirmButton === false || data.showConfirmButton === true) {
this.showConfirmButton = data.showConfirmButton
} else {
this.showConfirmButton = true
}
if (data.showConfirmCountdown === false || data.showConfirmCountdown === true) {
this.showConfirmCountdown = data.showConfirmCountdown
} else {
this.showConfirmCountdown = false
}
if (data.showCancelButton === false || data.showCancelButton === true) {
this.showCancelButton = data.showCancelButton
} else {
this.showCancelButton = true
}
if (data.success) {
this.success = data.success
} else {
this.success = () => {}
}
setTimeout(res => {
this.show = true;
}, 500)
if (this.showConfirmCountdown) {
this.startTimer();
}
},
startTimer() {
this.seconds = 3;
clearInterval(this.timer)
this.timer = setInterval(() => {
this.seconds--
// console.log("", this.seconds);
if (this.seconds <= 0) {
this.timeUp()
return
}
}, 1000)
},
timeUp() {
// clearInterval(this.timer)
console.log('时间到')
this.confirmClose();
},
},
}
</script>
<style lang="scss" scoped>
.slot-content {
font-size: 36rpx;
display: flex; //
flex-direction: column; //
align-items: center; //
// background-image: url()
}
.icon {
width: 70rpx;
height: 70rpx;
opacity: 1; //
margin-top: 16px;
}
.title {
font-size: 35rpx;
}
.content {
margin-top: 16px;
margin-bottom: 16px;
margin-left: 8px;
margin-right: 8px;
font-size: 32rpx;
text-align: center;
word-wrap: break-word;
word-break: break-all;
white-space: pre-line;
}
.cance_button {
width: 100%;
margin-top: 10px;
margin-bottom: 10px;
font-size: 32rpx;
display: flex;
justify-content: center;
align-items: center;
}
.confirm_button {
width: 100%;
margin-top: 10px;
margin-bottom: 10px;
font-size: 32rpx;
display: flex;
justify-content: center;
align-items: center;
}
.confirm_text {
// color: $uni-color-primary;
}
.def_text {
color: $uni-color-primary;
}
</style>

175
src/components/tab-nvue/mediaList.vue

@ -0,0 +1,175 @@
<template>
<view class="view">
<view class="list-cell view" hover-class="uni-list-cell-hover" @click="bindClick">
<view class="media-list view" v-if="options.title">
<view class="view" :class="{'media-image-right': options.article_type === 2, 'media-image-left': options.article_type === 1}">
<text class="media-title" :class="{'media-title2': options.article_type === 1 || options.article_type === 2}">{{options.title}}</text>
<view v-if="options.image_list || options.image_url" class="image-section view" :class="{'image-section-right': options.article_type === 2, 'image-section-left': options.article_type === 1}">
<image class="image-list1" :class="{'image-list2': options.article_type === 1 || options.article_type === 2}"
v-if="options.image_url" :src="options.image_url"></image>
<image class="image-list3" v-if="options.image_list" :src="source.url" v-for="(source, i) in options.image_list"
:key="i" />
</view>
</view>
<view class="media-foot view">
<view class="media-info view">
<text class="info-text">{{options.source}}</text>
<text class="info-text">{{options.comment_count}}条评论</text>
<text class="info-text">{{options.datetime}}</text>
</view>
<view class="max-close-view view" @click.stop="close">
<view class="close-view view"><text class="close">×</text></view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
options: {
type: Object,
default: function(e) {
return {}
}
}
},
methods: {
close(e) {
this.$emit('close');
},
bindClick() {
this.$emit('click');
}
}
}
</script>
<style>
.view {
display: flex;
flex-direction: column;
box-sizing: border-box;
}
.list-cell {
width: 750rpx;
padding: 0 30rpx;
}
.uni-list-cell-hover {
background-color: #eeeeee;
}
.media-list {
flex: 1;
flex-direction: column;
border-bottom-width: 1rpx;
border-bottom-style: solid;
border-bottom-color: #c8c7cc;
padding: 20rpx 0;
}
.media-image-right {
flex-direction: row;
}
.media-image-left {
flex-direction: row-reverse;
}
.media-title {
flex: 1;
}
.media-title {
lines: 3;
text-overflow: ellipsis;
font-size: 32rpx;
color: #555555;
}
.media-title2 {
flex: 1;
margin-top: 6rpx;
line-height: 40rpx;
}
.image-section {
margin-top: 20rpx;
flex-direction: row;
justify-content: space-between;
}
.image-section-right {
margin-top: 0rpx;
margin-left: 10rpx;
width: 225rpx;
height: 146rpx;
}
.image-section-left {
margin-top: 0rpx;
margin-right: 10rpx;
width: 225rpx;
height: 146rpx;
}
.image-list1 {
width: 690rpx;
height: 481rpx;
}
.image-list2 {
width: 225rpx;
height: 146rpx;
}
.image-list3 {
width: 225rpx;
height: 146rpx;
}
.media-info {
flex-direction: row;
}
.info-text {
margin-right: 20rpx;
color: #999999;
font-size: 24rpx;
}
.media-foot {
margin-top: 20rpx;
flex-direction: row;
justify-content: space-between;
}
.max-close-view {
align-items: center;
justify-content: flex-end;
flex-direction: row;
height: 40rpx;
width: 80rpx;
}
.close-view {
border-style: solid;
border-width: 1px;
border-color: #999999;
border-radius: 10rpx;
justify-content: center;
height: 30rpx;
width: 40rpx;
line-height: 30rpx;
}
.close {
text-align: center;
color: #999999;
font-size: 28rpx;
}
</style>

5046
src/components/u-charts/u-charts.js

File diff suppressed because it is too large

24
src/libs/versionUpdate.js

@ -0,0 +1,24 @@
import axios from 'axios'
const isNewVersion = () => {
let updae_url=""
// let updae_url = getApp().globalData.text;
let url = updae_url+ `/static/version.json?t=${new Date().getTime()}`
axios.get(url).then(res => {
if (res.status === 200) {
let vueVersion = res.data.version;
let localVueVersion = localStorage.getItem('vueVersion');
if (localVueVersion && localVueVersion != vueVersion) {
localStorage.setItem('vueVersion', vueVersion);
window.location.reload();
return;
} else {
localStorage.setItem('vueVersion', vueVersion);
}
}
})
}
export default {
isNewVersion
}

76
src/main.js

@ -0,0 +1,76 @@
import App from './App'
import store from './store'
import './router/my_router.js'; //引入拦截
import VueClipboard from 'vue-clipboard2' //复制粘贴
import uView from './uni_modules/vk-uview-ui';// 引入 uView UI
// import uView2 from './components/uview-ui'
import comMessage from './mycomponents/common/comMessage.vue'
// #ifndef VUE3
import Vue from 'vue'
console.log("Vuew2222");
Vue.config.productionTip = false
Vue.prototype.$store = store
Vue.prototype.$adpid = "1111111111"
Vue.prototype.$backgroundAudioData = {
playing: false,
playTime: 0,
formatedPlayTime: '00:00:00'
}
App.mpType = 'app'
const app = new Vue({
store,
...App
})
app.$mount()
// #endif
import {
createSSRApp
} from "vue";
export function createApp() {
const app = createSSRApp(App);
app.use(store)
app.use(VueClipboard)
app.use(uView)
// app.use(uView2)
app.component('comMessage', comMessage)
console.log("网络22请求")
// startApp(app);
return {
app,
};
}
export function startApp(app) {
uni.request({
url: `./static/config.json?t=${new Date().getTime()}`,
method: 'get',
data: {},
success: (res) => {
if (res.data != "") {
//在配置中读url,company等信息
// app.config.globalProperties.$baseInfo = res.data.baseInfo;
// getApp().globalData.dev_url = res.data.baseInfo.dev.value;
// getApp().globalData.request_url = res.data.baseInfo.request_url.value;
// getApp().globalData.tenantId = res.data.baseInfo.tenantId.value;
// app.config.globalProperties.$recepit_configList = res.data.recepit_configList;
// getApp().globalData.recepit_configList = res.data.recepit_configList;
// getApp().globalData.feed_configList = res.data.feed_configList;
// getApp().globalData.isDevelopment = res.data.baseInfo.isDevelopment.value
// Vue.prototype.$dev_url = res.data.baseInfo.dev.value;
// console.log("网络",res.data.baseInfo.request_url.value)
// console.log("开发环境12",res.data.baseInfo.isDevelopment.value)
// uni.setStorageSync("request_url",res.data.baseInfo.request_url.value)
// uni.setStorageSync("isDevelopment",res.data.baseInfo.isDevelopment.value)
}
},
fail: (error) => {
}
})
return {
startApp
};
}

85
src/manifest.json

@ -0,0 +1,85 @@
{
"name" : "wms",
"appid" : "__UNI__43932FE",
"description" : "",
"versionName" : "1.0.0",
"versionCode" : 1,
"transformPx" : false,
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"compatible" : {
"ignoreVersion" : true //trueHBuilderX1.9.0
},
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* */
"modules" : {
"Bluetooth" : {},
"Barcode" : {},
"Camera" : {}
},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
],
"abiFilters" : [ "armeabi-v7a", "arm64-v8a", "x86" ],
"minSdkVersion" : 23
},
/* ios */
"ios" : {
"dSYMs" : false
},
/* SDK */
"sdkConfigs" : {
"ad" : {}
}
}
},
/* */
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false
},
"usingComponents" : true
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "3"
}

147
src/mycomponents/balance/balance.vue

@ -0,0 +1,147 @@
<template>
<view :class="dataContent.scaned?'scan_view':''" style="background-color: #ffffff;margin-bottom: 1px; ">
<view class="uni-flex uni-row space-between" style="align-items: center">
<view>
<pack v-if="isShowPack && dataContent.packingNumber" :packingCode="dataContent.packingNumber"></pack>
<batch v-if="isShowBatch && dataContent.batch" :batch="dataContent.batch"></batch>
<location title="来源库位" v-if="isShowFromLocation" :locationCode="dataContent.locationCode"></location>
<to-location title="目标库位" v-if="isShowToLocation" :locationCode="dataContent.toLocationCode">
</to-location>
</view>
<view>
<!-- <qty v-if="dataContent.record==null ||dataContent.record==undefined " :dataContent="dataContent"
:isShowStdPack="isShowStdPack" :isShowStatus="isShowStatus"></qty> -->
<qty v-if="dataContent.handleQty==0 || dataContent.handleQty==undefined" :dataContent="dataContent"
:isShowStdPack="isShowStdPack" :isShowStatus="isShowStatus"></qty>
<compare-qty v-else :dataContent="dataContent" :recommendQty="Number( dataContent.qty)"
:handleQty="Number (dataContent.handleQty)" :isShowStdPack="isShowStdPack">
</compare-qty>
<view class="uni-flex uni-row" style="vertical-align:center" v-if="isDevlement()">
<text style="font-size: 30rpx;color: #2979ff; " @click="copy">复制采购</text>
<text style="font-size: 30rpx;color: #2979ff;" @click="copyPro">|制品</text>
</view>
</view>
</view>
<!-- <u-line></u-line> -->
</view>
</template>
<script>
import pack from '@/mycomponents/balance/pack.vue'
import location from '@/mycomponents/balance/location.vue'
import toLocation from '@/mycomponents/balance/toLocation.vue'
import batch from '@/mycomponents/balance/batch.vue'
import qty from '@/mycomponents/qty/qty.vue'
import recommendQty from '@/mycomponents/qty/recommendQty.vue'
import compareQty from '@/mycomponents/qty/compareQty.vue'
import config from '@/static/config.js'
export default {
components: {
pack,
location,
toLocation,
batch,
qty,
recommendQty,
compareQty,
},
data() {
return {
}
},
props: {
dataContent: {
type: Object,
default: {}
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowFromLocation: {
type: Boolean,
default: true
},
isShowStdPack: {
type: Boolean,
default: true
},
isShowStatus: {
type: Boolean,
default: true
},
isShowToLocation: {
type: Boolean,
default: false
},
},
watch: {
},
methods: {
copy() {
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100
var content = "HPQ;V1.0;I" + this.dataContent.itemCode + ";P" + this.dataContent.packingNumber + ";B" +
this.dataContent.batch + ";Q" + this.dataContent.qty
// #ifdef H5
this.$copyText(content).then(
res => {
uni.showToast({
title: '复制成功',
icon: 'none'
})
}
)
// #endif
// #ifndef H5
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制采购标签成功'
})
}
})
// #endif
},
copyPro() {
// HPQ;V1.0;ICE115F11161AG;PP20230427000026;B20230427002;Q100
var content = "HMQ;V1.0;I" + this.dataContent.itemCode + ";P" + this.dataContent.packingNumber + ";B" +
this.dataContent.batch + ";Q" + this.dataContent.qty
// #ifdef H5
this.$copyText(content).then(
res => {
uni.showToast({
title: '复制成功',
icon: 'none'
})
}
)
// #endif
// #ifndef H5
uni.setClipboardData({
data: content,
success: () => {
uni.showToast({
title: '复制制品标签成功'
})
}
})
// #endif
},
isDevlement() {
return config.isDevelopment;
}
}
}
</script>
<style>
</style>

88
src/mycomponents/balance/balanceDetailPopup.vue

@ -0,0 +1,88 @@
<template>
<uni-popup ref="popup">
<view class="pop_detail" style="height:80%">
<!-- <com-item :dataContent="dataContent.package"></com-item>
<u-line></u-line>
<scroll-view style="height:320px ">
<view v-for="(item, index) in dataList" style="width: 100%;">
<view class="item">
<text class="item_title">{{item.item_title}} </text>
<text v-if="(item.type=='')||(item.type==undefined)" class="text_wrap">{{item.content}} </text>
<text v-else-if="item.type=='dateTime'" class="text_wrap">{{formatDate(item.content)}} </text>
<text v-else-if="item.type=='boolean'" class="text_wrap">{{boolean(item.content)}} </text>
</view>
</view>
</scroll-view> -->
<view class="uni-flex u-row-center ">
<view class="close_button" @click="closePopup">
关闭</view>
<!-- button 滚动不好使 -->
</view>
</view>
</uni-popup>
</template>
<script>
import detailItemInfo from '@/mycomponents/detail/detailItemInfo.vue'
import detailBalanceInfo from '@/mycomponents/detail/detailBalanceInfo.vue'
import detailPackageInfo from '@/mycomponents/detail/detailPackageInfo.vue'
import {
dateFormat
} from '@/common/basic.js';
export default {
emits: ['onClose'],
components: {
detailItemInfo,
detailBalanceInfo,
detailPackageInfo
},
data() {
return {
dataContent: {
type: Object,
default: {}
},
dataList: []
}
},
mounted() {},
props: {
},
methods: {
openPopup(val) {
this.dataContent = val;
setTimeout(res => {
this.$refs.popup.open('bottom')
}, 500)
},
// avaliable(value) {
// return value == "TRUE" ? "" : ""
// },
// boolean(value) {
// return value == "TRUE" ? "" : ""
// },
// formatDate(val) {
// return dateFormat(val)
// },
closePopup(val) {
this.$refs.popup.close('bottom')
// this.$emit('onClose')
},
}
}
</script>
<style>
</style>

57
src/mycomponents/balance/balanceLabel.vue

@ -0,0 +1,57 @@
<template>
<view :class="dataContent.scaned?'scan_view':''">
<balance :dataContent="dataContent" :isShowStdPack="false" :isShowPack="isShowPack" :isShowFromLocation="isShowLocation"></balance>
<purchase-info :dataContent="packageContent"></purchase-info>
</view>
</template>
<script>
import balance from '@/mycomponents/balance/balance.vue'
import purchaseInfo from '@/mycomponents/purchase/purchaseInfo.vue'
export default {
components: {
balance,
purchaseInfo
},
data() {
return {
}
},
props: {
dataContent: {
type: Object,
default: {}
},
packageContent: {
type: Object,
default: {}
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowLocation: {
type: Boolean,
default: true
},
isShowStdPack: {
type: Boolean,
default: true
}
},
watch: {
},
methods: {
}
}
</script>
<style>
</style>

98
src/mycomponents/balance/balanceMove.vue

@ -0,0 +1,98 @@
<template>
<view :class="dataContent.scaned?'scan_view':''">
<view class="uni-flex uni-row space-between uni-inline-item">
<view>
<pack v-if="isShowPack" :packingCode="dataContent.packingNumber"></pack>
<batch v-if="isShowBatch" :batch="dataContent.batch"></batch>
<location v-if="isShowLocation" :locationCode="dataContent.locationCode"></location>
</view>
<view>
<qty :isShowStatus="dataContent.inventoryStatus==dataContent.toInventoryStatus" v-if="dataContent.record==null ||dataContent.record==undefined " :dataContent="dataContent"
:isShowStdPack="isShowStdPack"></qty>
<compare-qty v-else :dataContent="dataContent" :recommendQty="dataContent.qty"
:handleQty="dataContent.record.qty" :isShowStdPack="isShowStdPack">
</compare-qty>
<moveStatus v-if="dataContent.inventoryStatus!=dataContent.toInventoryStatus" :fromInventoryStatus="fromInventoryStatus" :toInventoryStatus="toInventoryStatus">
</moveStatus>
</view>
</view>
<u-line></u-line>
</view>
</template>
<script>
import pack from '@/mycomponents/balance/pack.vue'
import location from '@/mycomponents/balance/location.vue'
import batch from '@/mycomponents/balance/batch.vue'
import qty from '@/mycomponents/qty/qty.vue'
import recommendQty from '@/mycomponents/qty/recommendQty.vue'
import compareQty from '@/mycomponents/qty/compareQty.vue'
import moveStatus from '@/mycomponents/balance/moveStatus.vue'
export default {
components: {
pack,
location,
batch,
qty,
recommendQty,
compareQty,
moveStatus
},
data() {
return {
}
},
props: {
dataContent: {
type: Object,
default: {}
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowLocation: {
type: Boolean,
default: true
},
isShowStdPack: {
type: Boolean,
default: true
},
isShowBusiness: {
type: Boolean,
default: false
},
scaned: {
type: Boolean,
default: true
},
fromInventoryStatus: {
type: String,
default: ""
},
toInventoryStatus: {
type: String,
default: ""
},
},
watch: {
},
methods: {
}
}
</script>
<style>
</style>

54
src/mycomponents/balance/balanceSelect.vue

@ -0,0 +1,54 @@
<!--发料任务卡片-->
<template>
<!-- <page-meta root-font-size="18px"></page-meta> -->
<uni-popup ref="popupItems" type="center">
<scroll-view scroll-y="true" style="background-color: #EEEEEE;height: 90vh;">
<item :dataContent="balanceItems[0]"></item>
<view class="popinpop count_shadow" style="width: 90vw;margin: 20rpx 20rpx 30rpx 20rpx;"
v-for="(item, index) in balanceItems" :key="item.id" @click="callback(item)">
<balance :dataContent="item"></balance>
</view>
</scroll-view>
</uni-popup>
</template>
<script>
import item from '@/mycomponents/item/item.vue'
import balance from '@/mycomponents/balance/balance.vue'
export default {
name: "balanceSelect",
emits: ['onSelectItem'],
components: {
item,
balance
},
data() {
return {
balanceItems: [],
};
},
//
props: {
// datacontent: {
// type: Object,
// value: null
// }
},
methods: {
openPopup(items) {
this.balanceItems = items;
this.$refs['popupItems'].open("center");
},
callback(item) {
this.$emit("onSelectItem", item);
this.$refs['popupItems'].close();
},
}
}
</script>
<style scoped lang="scss">
</style>

24
src/mycomponents/balance/batch.vue

@ -0,0 +1,24 @@
<template>
<view class="card_view ">
<text class="card_batch card_content ">批次</text>
<text class="card_content ">{{batch}}</text>
</view>
</template>
<script>
export default {
data() {
return {}
},
props: {
batch: {
type: String,
default: ""
}
},
}
</script>
<style>
</style>

37
src/mycomponents/balance/bussinessType.vue

@ -0,0 +1,37 @@
<template>
<view class="business_view">
<text class="card_business">{{businessTypeDesc(bussinessType)}}</text>
<text class="card_business_content">{{number}}</text>
</view>
</template>
<script>
import {
getBusinessTypeDesc
} from '@/common/directory.js';
export default {
data() {
return {}
},
props: {
bussinessType: {
type: String,
default: ""
},
number: {
type: String,
default: ""
}
},
methods:{
businessTypeDesc(type){
return getBusinessTypeDesc(type)
}
}
}
</script>
<style>
</style>

80
src/mycomponents/balance/handleBalance.vue

@ -0,0 +1,80 @@
<template>
<view :class="detail.scaned?'scan_view':''" style="background-color: #ffffff;">
<view class="space_between center" >
<view style="word-break: break-all;width: 60%;">
<pack v-if="isShowPack" :packingCode="detail.packingNumber"></pack>
<batch v-if="isShowBatch" :batch="detail.batch"></batch>
<location v-if="isShowLocation" :locationCode="detail.fromLocationCode"></location>
</view>
<view style="word-break: break-all;">
<recommend-qty v-if="detail.record==null || detail.record==undefined" :dataContent="detail"
:isShowStdPack="false"></recommend-qty>
<compare-qty v-else :dataContent="detail" :recommendQty="detail.qty" :handleQty="detail.record.qty"
:isShowStdPack="false">
</compare-qty>
</view>
</view>
</view>
</template>
<script>
import pack from '@/mycomponents/balance/pack.vue'
import location from '@/mycomponents/balance/location.vue'
import batch from '@/mycomponents/balance/batch.vue'
import recommendQty from '@/mycomponents/qty/recommendQty.vue'
import compareQty from '@/mycomponents/qty/compareQty.vue'
export default {
components: {
pack,
location,
batch,
recommendQty,
compareQty
},
data() {
return {
}
},
props: {
detail: {
type: Object,
default: {}
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowLocation: {
type: Boolean,
default: true
},
},
watch: {
},
methods: {
}
}
</script>
<style>
.recommend {
position: absolute;
left: 25px;
top: 70px;
width: 10px;
height: 30px;
opacity: 1;
}
</style>

31
src/mycomponents/balance/location.vue

@ -0,0 +1,31 @@
<template>
<view class="card_view ">
<text class="card_location card_content ">{{title}}</text>
<text class="card_content ">{{locationCode}}</text>
</view>
</template>
<script>
export default {
components: {
},
data() {
return {}
},
props: {
locationCode: {
type: String,
default: ''
},
title: {
type: String,
default: '库位'
},
},
}
</script>
<style>
</style>

62
src/mycomponents/balance/moveStatus.vue

@ -0,0 +1,62 @@
<template>
<view class="uni-row uni-flex center" style="font-size: 30rpx;">
<status :status='fromInventoryStatus' :showDesc="true"></status>
<view class="uni-flex uni-row center"
v-if='showToInventoryStatus && toInventoryStatus!="" && toInventoryStatus!=fromInventoryStatus'>
<text style="color:#909399 ; ">
>
</text>
<status :status='toInventoryStatus' :showDesc="true"></status>
</view>
</view>
</template>
<script>
import {
getInventoryStatusStyle,
getInventoryStatusName
} from '@/common/directory.js';
import status from '@/mycomponents/status/status.vue'
export default {
components: {
status
},
data() {
return {
}
},
props: {
fromInventoryStatus: {
type: String,
default: ''
},
toInventoryStatus: {
type: String,
default: ''
},
showToInventoryStatus: {
type: Boolean,
default: false
},
},
watch: {
},
methods: {
statusStyle(value) {
return getInventoryStatusStyle(value);
},
statusDesc(value) {
return getInventoryStatusName(value)
}
}
}
</script>
<style>
</style>

34
src/mycomponents/balance/pack.vue

@ -0,0 +1,34 @@
<template>
<view class="card_view">
<text class="card_packing_code card_content ">包装</text>
<text class="card_content ">{{packingCode}}</text>
</view>
</template>
<script>
export default {
components: {
},
data() {
return {
}
},
props: {
packingCode: {
type: String,
default: ''
},
},
watch: {
},
methods: {
}
}
</script>
<style>
</style>

59
src/mycomponents/balance/productionLabel.vue

@ -0,0 +1,59 @@
<template>
<view :class="dataContent.scaned?'scan_view':''">
<balance :dataContent="dataContent" :isShowStdPack="false" :isShowPack="isShowPack"
:isShowFromLocation="isShowLocation"></balance>
<production-info :dataContent="packageContent"></production-info>
</view>
</template>
<script>
import balance from '@/mycomponents/balance/balance.vue'
import productionInfo from '@/mycomponents/production/productionInfo.vue'
export default {
components: {
balance,
productionInfo
},
data() {
return {
}
},
props: {
dataContent: {
type: Object,
default: {}
},
packageContent: {
type: Object,
default: {}
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowLocation: {
type: Boolean,
default: true
},
isShowStdPack: {
type: Boolean,
default: true
}
},
watch: {
},
methods: {
}
}
</script>
<style>
</style>

58
src/mycomponents/balance/purchaseLabel.vue

@ -0,0 +1,58 @@
<template>
<view :class="dataContent.scaned?'scan_view':''">
<balance :dataContent="dataContent" :isShowStdPack="false" :isShowPack="isShowPack"
:isShowFromLocation="isShowLocation"></balance>
<!-- <purchase-info :dataContent="packageContent"></purchase-info> -->
</view>
</template>
<script>
import balance from '@/mycomponents/balance/balance.vue'
import purchaseInfo from '@/mycomponents/purchase/purchaseInfo.vue'
export default {
components: {
balance,
purchaseInfo
},
data() {
return {
}
},
props: {
dataContent: {
type: Object,
default: {}
},
packageContent: {
type: Object,
default: {}
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowLocation: {
type: Boolean,
default: true
},
isShowStdPack: {
type: Boolean,
default: true
}
},
watch: {
},
methods: {
}
}
</script>
<style>
</style>

84
src/mycomponents/balance/recommendBalance.vue

@ -0,0 +1,84 @@
<template>
<view :class="detail.scaned?'scan_view':''" style="background-color: #fff;">
<view class="uni-flex uni-row space-between center ">
<view class="uni-flex uni-row " style="width: 60%;margin-left: 30rpx;" >
<view style=" width: 25rpx;color: #32C1E8;">
推荐
</view>
<view style="word-break: break-all">
<pack v-if="isShowPack" :packingCode="detail.packingNumber"></pack>
<batch v-if="isShowBatch" :batch="detail.batch"></batch>
<location v-if="isShowLocation" :locationCode="detail.fromLocationCode"></location>
</view>
</view>
<view style="word-break: break-all">
<recommend-qty v-if="detail.Records==null || detail.Records.length==0" :dataContent="detail"
:isShowStdPack="false" :isShowStatus="false"></recommend-qty>
<compare-qty v-else :dataContent="detail" :recommendQty="Number( detail.qty)"
:handleQty="Number(detail.handleQty)" :isShowStdPack="false" :isShowStatus="false">
</compare-qty>
</view>
</view>
</view>
</template>
<script>
import pack from '@/mycomponents/balance/pack.vue'
import location from '@/mycomponents/balance/location.vue'
import batch from '@/mycomponents/balance/batch.vue'
import recommendQty from '@/mycomponents/qty/recommendQty.vue'
import compareQty from '@/mycomponents/qty/compareQty.vue'
export default {
components: {
pack,
location,
batch,
recommendQty,
compareQty
},
data() {
return {
}
},
props: {
detail: {
type: Object,
default: {}
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowLocation: {
type: Boolean,
default: true
},
},
watch: {
},
methods: {
}
}
</script>
<style>
.recommend {
position: absolute;
left: 25px;
top: 70px;
width: 10px;
height: 30px;
opacity: 1;
}
</style>

31
src/mycomponents/balance/toLocation.vue

@ -0,0 +1,31 @@
<template>
<view class="card_view ">
<text class="card_to_location card_content ">{{title}}</text>
<text class="card_content ">{{locationCode}}</text>
</view>
</template>
<script>
export default {
components: {
},
data() {
return {}
},
props: {
locationCode: {
type: String,
default: ''
},
title: {
type: String,
default: '库位'
},
},
}
</script>
<style>
</style>

25
src/mycomponents/batch/batch.vue

@ -0,0 +1,25 @@
<template>
<view class="batch_view">
<text class="card_batch">批次</text>
<text class="card_batch_content">&nbsp{{batch}}</text>
</view>
</template>
<script>
export default {
data(){
return {
}
},
props: {
batch:{
type: String,
default: ""
}
},
}
</script>
<style>
</style>

57
src/mycomponents/button/requestButton.vue

@ -0,0 +1,57 @@
<template>
<view>
<view class="scan_float" @click="goScan('bottom')">
<image src="@/static/icons_ui/icon_add.svg"></image>
<view>{{btnName}}</view>
</view>
<!-- <movable-area>
<movable-view class="max" direction="all">扫描</movable-view>
</movable-area> -->
</view>
</template>
<script>
export default {
data() {
return {
x: 0,
y: 0,
old: {
x: 0,
y: 0
}
}
},
props: {
btnName: {
type: String,
default: '创建'
},
},
created() {
},
methods: {
goScan(content) {
this.$emit("goScan", '');
},
tap: function(e) {
this.x = this.old.x
this.y = this.old.y
this.$nextTick(function() {
this.x = 30
this.y = 30
})
},
onChange: function(e) {
this.old.x = e.detail.x
this.old.y = e.detail.y
}
},
}
</script>
<style>
</style>

31
src/mycomponents/common/comBlankView.vue

@ -0,0 +1,31 @@
<template>
<view class="default_goscan">
<image class="img_goscan" src="@/static/icons_ui/default_blank.png"></image>
<button @click="goScan">
<image src="@/static/icons_ui/icon_add.svg"></image>
去扫描
</button>
</view>
</template>
<script>
export default {
data() {
return {
}
},
created() {
},
methods: {
goScan(content) {
this.$emit("goScan", '');
}
}
}
</script>
<style>
</style>

41
src/mycomponents/common/comEmptyView.vue

@ -0,0 +1,41 @@
<template>
<view class=" " >
<view class="">
<image class="default_nodata" src="@/static/icons_ui/default_data.png"></image>
</view>
<!--
<view class="" style="display: flex;flex-direction: column;
align-items: center;">
<view class="" >
<image class="nodata" src="/static/icons_ui/default_data.png"></image>
</view>
<view style="font-size: 40rpx;color: #909193;">
暂无数据
</view>
</view> -->
</view>
</template>
<script>
export default {
data() {
return {
}
},
created() {
},
methods: {
}
}
</script>
<style>
</style>

162
src/mycomponents/common/comListHint.vue

@ -0,0 +1,162 @@
<template>
<view class="">
<uni-popup ref="popup">
<view class="uni-flex uni-column pop_detail">
<view class="uni-flex space-between u-col-center"
style="padding-bottom: 15rpx;">
<view class="text_ellipsis" v-if="number" style="font-size: 35rpx;flex: 3;">
编号:{{number}}
</view>
<view class="text_ellipsis" v-else style="font-size: 40rpx;">
<view class="">
{{itemCode}}
</view>
<view class="">
{{itemDesc}}
</view>
</view>
<view class="uni-center" style="flex: 1;">
<view v-if="jobStatus==2" class="task_state_doing">
<text>执行中</text>
</view>
<view v-if="jobStatus==1" class="task_state_un-doing">
<text>待执行</text>
</view>
</view>
<!-- <view class="" v-else="number">
<view class="text_ellipsis" style="font-size: 40rpx;flex: 1;">
<view class="">
{{itemCode}}
</view>
<view class="">
{{itemDesc}}
</view>
</view>
</view> -->
</view>
<u-line></u-line>
<view class="" v-for="(item, index) in dataList">
<view class="item" v-if="(item.title!='worker')" v-show="(item.title!='date')">
<text class="item_title">{{item.title}} : </text>
<text class="text_wrap">{{item.content}} </text>
</view>
</view>
<u-line></u-line>
<view v-if="isShowbottom" style="margin-top: 10rpx;margin-bottom: 10rpx;width: 100%;display: flex;"
class="uni-flex uni-row space-between u-col-center">
<view class="uni-flex uni-row u-col-center " style="flex: 1; overflow: hidden;">
<image class="card_icon_normal" src="/static/icons/icon_customer.svg" alt="" />
<text class="text_ellipsis">{{getContent("worker")}}</text>
</view>
<view class="uni-flex uni-row u-col-center " style="flex: 3;justify-content: flex-end;overflow: hidden;">
<image class="card_icon_normal" src="/static/icons/icon_date.svg" alt="" />
<text>{{formatDate(getContent("date"))}}</text>
</view>
</view>
</view>
<view class="uni-flex u-row-center ">
<image src="/static/icons/icons_close-circle.svg"
mode=""
class="icons_close"
@click="closeScanPopup()"
></image>
</view>
</uni-popup>
</view>
</template>
<script>
import {
dateFormat,
} from '@/common/basic.js';
export default {
mounted() {
},
props: {
title: {
type: String,
default: ""
},
dataContent: {
type: Object,
default: {}
},
number:{
type: String,
default: ""
},
jobStatus:{
type: Number,
default: -1
},
dataList:{
type: Object,
default: []
},
worker:{
type: String,
default: ""
},
date:{
type: String,
default: ""
},
itemCode:{
type: String,
default: ""
},
itemDesc:{
type: String,
default: ""
},
isShowbottom:{
type: Boolean,
default: true
}
},
methods: {
openScanPopup() {
this.$refs.popup.open('center')
},
closeScanPopup() {
this.$refs.popup.close()
},
startEdit() {
this.$refs.receiptCountEdit.openScanPopup();
},
formatDate(val) {
return dateFormat(val)
},
statusColor: function(val) {
return getJobStatuDesc(val);
},
getContent(title){
let items = this.dataList.filter(r => {
if (r.title==title) {
return r;
}
})
if(items!=null&&items.length>0){
return items[0].content;
}
}
}
}
</script>
<style>
</style>

108
src/mycomponents/common/comListItem.vue

@ -0,0 +1,108 @@
<template>
<view class="">
<view class="uni-flex uni-column">
<view class="item" v-for="(item,index) in dataList">
<text class="item_title">{{item.title}} : </text>
<text v-if="(item.type=='')||(item.type==undefined)" class="text_wrap">{{item.content}} </text>
<text v-else-if="item.type=='dateTime'" class="text_wrap">{{formatDate(item.content)}} </text>
<text v-else-if="item.type=='boolean'" class="text_wrap">{{boolean(item.content)}} </text>
<text v-else-if="item.type=='transferMode'" class="text_wrap">{{getTransferModeName(item.content)}} </text>
<text v-else-if="item.type=='locationType'" class="text_wrap">{{getLocationTypeNameList(getDirectoryItemArray(item.content))}} </text>
<text v-else-if="item.type=='uom'" class="text_wrap">{{getUomInfo(item.content)}} </text>
<text v-else-if="item.type=='inspectType'" class="text_wrap">{{getInspectType(item.content)}} </text>
<text v-else-if="item.type=='sampleMethod'" class="text_wrap">{{getSampleMethod(item.content)}} </text>
<text v-else-if="item.type=='requestState'" class="text_wrap">{{getRequestStateInfo(item.content)}} </text>
<text v-else-if="item.type=='inventoryStatus'" class="text_wrap">{{getInventoryStatusName(item.content)}} </text>
<text v-else-if="item.type=='locationCode'" class="text_wrap">{{getLocationTypeName(item.content)}} </text>
</view>
</view>
</view>
</template>
<script>
import {
dateFormat
} from '@/common/basic.js';
import {
getTransferModeName,
getLocationTypeNameList,
getDirectoryItemArray,
getUomInfo,
getInspectType,
getSampleMethod,
getRequestStateInfo,
getInventoryStatusName,
getLocationTypeName
} from '@/common/directory.js';
export default {
components: {},
data() {
return {
}
},
mounted() {},
watch: {
// dataContent: {
// handler(newName, oldName) {
// },
// immediate: true,
// deep: true
// }
},
props: {
dataList: {
type: Array,
default: []
}
},
methods: {
avaliable(value) {
return value == "TRUE" ? "可用" : "不可用"
},
boolean(value) {
return value == "TRUE" ? "是" : "否"
},
formatDate(val) {
return dateFormat(val)
},
getTransferModeName(value){
return getTransferModeName(value)
},
getLocationTypeNameList(value){
return getLocationTypeNameList(value)
},
getDirectoryItemArray(value){
return getDirectoryItemArray(value)
},
getUomInfo(value){
return getUomInfo(value).label
},
getInspectType(value){
return getInspectType(value)
},
getSampleMethod(value){
return getSampleMethod(value)
},
getRequestStateInfo(value){
return getRequestStateInfo(value).label
},
getInventoryStatusName(value){
return getInventoryStatusName(value)
},
getLocationTypeName(value){
return getLocationTypeName(value)
}
}
}
</script>
<style>
</style>

479
src/mycomponents/common/comMessage.vue

@ -0,0 +1,479 @@
<template name="show-modal">
<view>
<u-modal v-model="show" :title-style="{color: 'red'}" :title="title" :showTitle="false"
:showConfirmButton="false" ref="modal">
<view class="slot-content">
<slot name="icon">
<image class="icon" :src="icon" />
</slot>
<slot name="content">
<rich-text class="content" :nodes="content">
</rich-text>
</slot>
<u-line></u-line>
<slot name="button">
<view class="uni-flex uni-row u-col-center space-between" style="width: 100%;height: 48px;">
<view v-if="showCancelButton" class="cance_button" @tap="cancelClose">
<text :style="{'color':cancelColor}">{{ cancelText }}</text>
</view>
<u-line direction="col" length="100%"></u-line>
<view v-if="showConfirmButton" class="confirm_button" @tap="confirmClose">
<text :style="{'color':confirmColor}">{{confirmText}}</text>
<text v-if="showConfirmCountdown">({{seconds}}s关闭)</text>
</view>
</view>
</slot>
</view>
</u-modal>
</view>
</template>
<script>
/**
* modal 模态框
* @description 弹出模态框常用于消息提示消息确认在当前页面内完成特定的交互操作
* */
export default {
data() {
return {
timer: null,
show: false, //
iconType: '消息',
icon: '../../static/icons/error-circle.svg',
title: '', //
content: '', //
cancelText: '取消', //
confirmText: '确定', //
showCancel: true, // true
confirmColor: '#007aff', //
cancelColor: null, //
showConfirmButton: true, //
showConfirmCountdown: true, //
showCancelButton: true, //
showClose: false,
confirm: false, // true
cancel: false, // true
isDisabled: true, // true
seconds: 0,
success: () => {} //
}
},
methods: {
open() {
this.show = true;
this.isDisabled = true;
},
close() {
this.$.refs.modal.popupClose();
this.isDisabled = false;
},
confirmClose() {
if (!this.isDisabled) return
this.isDisabled = false
// console.log('')
if (this.show) {
this.show = false;
clearInterval(this.timer) //timer
this.$.refs.modal.popupClose();
this.success({
// cancel: false,
confirm: true,
});
}
},
cancelClose() {
if (!this.isDisabled) return
this.isDisabled = false
clearInterval(this.timer) //timer
this.$.refs.modal.popupClose();
this.success({
// cancel: true,
confirm: false,
});
},
// (+)
showMessage(mContent, callback) {
this.showConfirmCountdownModal("消息", mContent, callback);
},
// (+)
showSuccessMessage(mContent, callback) {
this.showConfirmCountdownModal("成功", mContent, callback);
},
// (
showErrorMessage(mContent, callback) {
this.showConfirmModal("失败", mContent, callback);
},
// (
showBreakMessage(mContent, callback) {
this.showNoButtonModal("失败", mContent, callback);
},
// (+
showQuestionMessage(mContent, callback) {
this.showSelectModal("疑问", mContent, callback);
},
// (+)
showWarningMessage(mContent, callback) {
this.showConfirmCountdownModal("警告", mContent, callback);
},
// (+)
showConfirmCountdownFailModal(mContent, callback) {
this.showConfirmCountdownModal("失败", mContent, callback);
},
// (
showConfirmMessageModal(mContent, callback) {
this.showConfirmModal("消息", mContent, callback);
},
// (
showConfirmSuccessModal(mContent, callback) {
this.showConfirmModal("成功", mContent, callback);
},
// (
showConfirmWarningModal(mContent, callback) {
this.showConfirmModal("警告", mContent, callback);
},
// (
showConfirmQuestionModal(mContent, callback) {
this.showConfirmModal("疑问", mContent, callback);
},
// (
showNoButtonModal(mIconType, mContent, callback) {
this.showModal({
iconType: mIconType,
content: mContent,
showConfirmButton:false,
showCancelButton: false,
success: function(res) {
if (callback != undefined) {
if (res.confirm == true) {
callback(true);
} else {
callback(false);
}
}
}
});
},
// (
showConfirmModal(mIconType, mContent, callback) {
this.showModal({
iconType: mIconType,
content: mContent,
showCancelButton: false,
success: function(res) {
if (callback != undefined) {
if (res.confirm == true) {
callback(true);
} else {
callback(false);
}
}
}
});
},
// (+
showSelectMessageModal(mContent, callback) {
this.showSelectModal("消息", mContent, callback);
},
// (+
showSelectSuccessModal(mContent, callback) {
this.showSelectModal("成功", mContent, callback);
},
// (+
showSelectFailModal(mContent, callback) {
this.showSelectModal("失败", mContent, callback);
},
// (+
showSelectWarningModal(mContent, callback) {
this.showSelectModal("警告", mContent, callback);
},
// (+
showSelectModal(mIconType, mContent, callback) {
this.showModal({
iconType: mIconType,
content: mContent,
success: function(res) {
if (callback != undefined) {
if (res.confirm == true) {
callback(true);
console.log('用户点击确定')
} else {
callback(false);
console.log('用户点击取消')
}
}
}
});
},
// (+)
showConfirmCountdownQuestionModal(mContent, callback) {
this.showConfirmCountdownModal("疑问", mContent, callback);
},
// (+)
showConfirmCountdownModal(mIconType, mContent, callback) {
this.showModal({
iconType: mIconType,
content: mContent,
showCancelButton: false,
showConfirmCountdown: true,
success: function(res) {
if (callback != undefined) {
if (res.confirm == true) {
callback(true);
} else {
callback(false);
}
}
}
});
},
// (++)
showSelectCountdownMessageModal(mContent, callback) {
this.showSelectCountdownModal("消息", mContent, callback);
},
// (++)
showSelectCountdownSuccessModal(mContent, callback) {
this.showSelectCountdownModal("成功", mContent, callback);
},
// (++)
showSelectCountdownFailModal(mContent, callback) {
this.showSelectCountdownModal("失败", mContent, callback);
},
// (++)
showSelectCountdownWarningModal(mContent, callback) {
this.showSelectCountdownModal("警告", mContent, callback);
},
// (++)
showSelectCountdownQuestionModal(mContent, callback) {
this.showSelectCountdownModal("疑问", mContent, callback);
},
// (++)
showSelectCountdownModal(mIconType, mContent, callback) {
this.showModal({
iconType: mIconType,
content: mContent,
showConfirmCountdown: true,
success: function(res) {
if (callback != undefined) {
if (res.confirm == true) {
callback(true);
console.log('用户点击确定')
} else {
callback(false);
console.log('用户点击取消')
}
}
}
});
},
//
showModal(data) {
if (data.iconType) {
this.iconType = data.iconType
switch (data.iconType) {
case '消息':
this.icon = '/static/icons/error-circle.svg';
break;
case '成功':
this.icon = '/static/icons/checkmark-circle.svg';
break;
case '失败':
this.icon = '/static/icons/close-circle.svg';
break;
case '警告':
this.icon = '/static/icons/warning.svg';
break;
case '疑问':
this.icon = '/static/icons/question-circle.svg';
break;
default:
break;
}
}
// image
if (data.title) {
this.title = data.title
}
if (data.content) {
this.content = data.content
} else {
this.content = ''
}
if (data.cancelText) {
this.cancelText = data.cancelText
} else {
this.cancelText = '取消'
}
if (data.confirmText) {
this.confirmText = data.confirmText
} else {
this.confirmText = '确定'
}
if (data.showCancel === false || data.showCancel === true) {
this.showCancel = data.showCancel
} else {
this.showCancel = true
}
if (data.confirmColor) {
this.confirmColor = data.confirmColor
} else {
this.confirmColor = '#007aff'
}
if (data.cancelColor) {
this.cancelColor = data.cancelColor
} else {
this.cancelColor = '#666F83'
}
if (data.showConfirmButton === false || data.showConfirmButton === true) {
this.showConfirmButton = data.showConfirmButton
} else {
this.showConfirmButton = true
}
if (data.showConfirmCountdown === false || data.showConfirmCountdown === true) {
this.showConfirmCountdown = data.showConfirmCountdown
} else {
this.showConfirmCountdown = false
}
if (data.showCancelButton === false || data.showCancelButton === true) {
this.showCancelButton = data.showCancelButton
} else {
this.showCancelButton = true
}
if (data.success) {
this.success = data.success
} else {
this.success = () => {}
}
setTimeout(res => {
this.open();
}, 500)
if (this.showConfirmCountdown) {
this.startTimer();
}
},
startTimer() {
this.seconds = 3;
clearInterval(this.timer)
this.timer = setInterval(() => {
this.seconds--
// console.log("", this.seconds);
if (this.seconds <= 0) {
this.timeUp()
return
}
}, 1000)
},
timeUp() {
// clearInterval(this.timer)
console.log('时间到')
this.confirmClose();
},
},
}
</script>
<style lang="scss" scoped>
.slot-content {
font-size: 36rpx;
display: flex; //
flex-direction: column; //
align-items: center; //
// background-image: url()
}
.icon {
width: 70rpx;
height: 70rpx;
opacity: 1; //
margin-top: 16px;
}
.title {
font-size: 35rpx;
}
.content {
width: 100%;
margin-top: 16px;
margin-bottom: 16px;
margin-left: 8px;
margin-right: 8px;
font-size: 32rpx;
text-align: center;
}
.cance_button {
width: 100%;
margin-top: 10px;
margin-bottom: 10px;
font-size: 32rpx;
display: flex;
justify-content: center;
align-items: center;
}
.confirm_button {
width: 100%;
margin-top: 10px;
margin-bottom: 10px;
font-size: 32rpx;
display: flex;
justify-content: center;
align-items: center;
}
.confirm_text {
// color: $uni-color-primary;
}
.def_text {
color: $uni-color-primary;
}
</style>

39
src/mycomponents/common/comPopup.vue

@ -0,0 +1,39 @@
<template>
<view>
<scroll-view scroll-y="true" style="height: 450px;">
<slot></slot>
</scroll-view>
<view class="uni-flex u-row-center">
<image src="/static/icons/icons_close-circle.svg" class="icons_close" @click="closeScanPopup()">
</image>
</view>
</view>
</template>
<script>
export default {
emits: ["onClose"],
components: {
},
props: {
},
data() {
return {
}
},
methods: {
closeScanPopup() {
this.$emit("onClose", );
}
}
}
</script>
<style>
</style>
<style>
</style>

120
src/mycomponents/common/comUploadCamera.vue

@ -0,0 +1,120 @@
<!--拍照上传-->
<template>
<view>
<!-- <button @click="camera">拍照</button> -->
<uni-file-picker ref="files" limit="3" title="最多选择3张图片" :auto-upload="false" v-model="imageValue"
:sizeType="sizeType" fileMediatype="image" mode="grid" file-extname="png,jpg" @select="select"
@delete="deleteImg" @progress="progress" @success="success"
:disabled="disabled" :del-icon='!disabled'
@fail="fail" />
</view>
</template>
<script>
export default {
name: "uploadCamera",
data() {
return {
imageValue: [],
sizeType: ['compressed']
}
},
props: {
disabled: {
type: Boolean,
value: false
}
},
watch: {},
methods: {
//
upload() {
this.$refs.files.upload()
},
//
select(e) {
console.log('选择文件:', e)
},
//
deleteImg(e) {
console.log('删除:', e)
},
//
progress(e) {
console.log('上传进度:', e)
},
//
success(e) {
console.log('上传成功')
},
//
fail(e) {
console.log('上传失败:', e)
},
getFiles() {
return this.$refs.files.files;
},
setFiles(files) {
this.$refs.files.files = files;
},
clearFiles() {
this.$refs.files.files = []
}
// camera(){
// let that = this
// uni.chooseImage({
// count: 3, //9
// sizeType: ['original'], //
// sourceType: ['camera'], //
// success: function (res) {
// console.log(res.tempFilePaths)
// console.log(JSON.stringify(res.tempFilePaths));
// that.select({
// tempFilePaths:[
// JSON.stringify(res.tempFilePaths[0])
// ],
// tempFiles:[
// {path: res.tempFilePaths[0]}
// ]})
// }
// });
// },
// camera(){
// // getCamera index 12使
// // ios
// const cmr = plus.camera.getCamera()
// //
// const res = cmr.supportedImageResolutions[0]
// //
// const fmt = cmr.supportedImageFormats[0]
// //
// cmr.captureImage((path) => {
// // this.compressImage(path)
// // path
// console.log(path)
// plus.gallery.save( path, function () {
// alert( "" );
// },(error) => {
// alert(error);
// });
// },
// (error) => {
// console.log('Capture image failed: ' + error.message)
// }, {
// resolution: res,
// format: fmt,
// filename:''
// })
// },
}
}
</script>
<style scoped lang="scss">
</style>

24
src/mycomponents/container/container.vue

@ -0,0 +1,24 @@
<template>
<view class="card_view ">
<text class="card_container card_content ">托码</text>
<text class="card_content ">{{container}}</text>
</view>
</template>
<script>
export default {
data() {
return {}
},
props: {
container: {
type: String,
default: ""
}
},
}
</script>
<style>
</style>

54
src/mycomponents/container/containerInfo.vue

@ -0,0 +1,54 @@
<!--包装组件-->
<template>
<view class="">
<view class="uni-flex space-between padding_10" style="background-color: #fff;" >
<view>
<view class="font_xl text_black text_bold">
{{ itemDetail.number }}
</view>
<view class="">
总容量 : {{ itemDetail.capacity }}
</view>
</view>
<view class="">
<containerStatus :status="itemDetail.status"></containerStatus>
</view>
</view>
<itemInfoPopup ref="showHint" :dataContent="itemDetail" :type="'partCode'"></itemInfoPopup>
</view>
</template>
<script>
import containerStatus from '@/mycomponents/container/containerStatus.vue';
import itemInfoPopup from '@/mycomponents/item/itemInfoPopup.vue';
export default {
name: "comItem",
components: {
itemInfoPopup,
containerStatus
},
data() {
return {
};
},
//
props: {
itemDetail: {
type: Object,
value: null
}
},
methods: {
showHint() {
this.$refs.showHint.openScanPopup()
}
}
}
</script>
<style>
</style>

47
src/mycomponents/container/containerStatus.vue

@ -0,0 +1,47 @@
<template>
<view class="">
<text :class="statusStyle(status)"
style="padding-top: 5rpx;padding-bottom: 5rpx;padding-left: 15rpx;padding-right: 15rpx;">{{statusDesc(status)}}</text>
</view>
</template>
<script>
import {
getContainerStatusInfo
} from '@/common/directory.js';
export default {
components: {
},
data() {
return {
};
},
props: {
dataContent: {
type: Object,
default: {},
},
status: {
type: String,
default: "",
},
},
methods: {
statusDesc(value) {
return getContainerStatusInfo(value).name
},
statusStyle(value) {
return getContainerStatusInfo(value).remark;
},
}
}
</script>
<style>
</style>

68
src/mycomponents/container/targetContainer.vue

@ -0,0 +1,68 @@
<template>
<view class="uni-flex u-col-center" style="padding-top: 15rpx;
padding-bottom: 15rpx;
padding-left: 10rpx;
padding-right: 10rpx;
font-size:32rpx;">
<text style="font-size: 35rpx;">{{title}} </text>
<view class="uni-flex u-col-center" @click="showLocation">
<text style="color:#3FBAFF;font-size: 35rpx;" v-if="containerCode==''&&isShowEdit==true">&nbsp 请扫描</text>
<text style="color:#3FBAFF; font-size: 35rpx;">&nbsp {{containerCode}}</text>
<image v-if="isShowEdit" style="width: 45rpx;height: 45rpx;" src="/static/icons/icons_edit.svg"></image>
</view>
<winScanContainer ref="scanContainer" :title="title" @getContainer='getContainer'></winScanContainer>
</view>
</template>
<script>
import winScanContainer from "@/mycomponents/scan/winScanContainer.vue"
export default {
components: {
winScanContainer
},
data() {
return {
defaultContainerCode: ""
}
},
props: {
title: {
type: String,
default: "需求库位"
},
containerCode: {
type: String,
default: ""
},
isShowEdit: {
type: Boolean,
default: true
},
},
watch: {
containerCode: {
handler(newName, oldName) {
if (this.containerCode != "") {
this.defaultContainerCode = this.containerCode;
}
},
immediate: true,
deep: true
}
},
methods: {
showLocation() {
this.$refs.scanContainer.openScanPopup();
},
//
getContainer(containerInfo) {
this.$emit("getContainer", containerInfo)
}
}
}
</script>
<style>
</style>

162
src/mycomponents/detail/comDetailCard.vue

@ -0,0 +1,162 @@
<template>
<view class="" style="background-color: #fff;">
<uni-collapse ref="collapse1" @change="">
<uni-collapse-item :open="true">
<template v-slot:title>
<item-compare-qty :dataContent="dataContent" :handleQty="dataContent.handleQty" :isShowStdPack="false">
</item-compare-qty>
</template>
<u-line></u-line>
<view class="" v-for="(item,index) in dataContent.subList" :key="index">
<uni-swipe-action ref="swipeAction">
<uni-swipe-action-item @click="swipeClick($event,item)"
:right-options="item.scaned?scanOptions:detailOptions"
style='padding:0px 0px 5px 0px;align-items: center;'>
<recommend :detail="item" :isShowToLocation="false">
</recommend>
</uni-swipe-action-item>
</uni-swipe-action>
</view>
</uni-collapse-item>
</uni-collapse>
<balance-qty-edit ref="qtyEdit" :settingParam="settingParam" @confirm="confirm"></balance-qty-edit>
<win-scan-location ref="scanLocationCode" title="目标库位" @getLocation='getLocation'
:locationAreaTypeList="locationAreaTypeList"></win-scan-location>
<comMessage ref="message"></comMessage>
</view>
</template>
<script>
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue'
import recommend from '@/mycomponents/recommend/recommend.vue'
import balanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue'
import winScanLocation from "@/mycomponents/scan/winScanLocation.vue"
import {
getDetailOption,
getPurchaseReceiptOption
} from '@/common/array.js';
export default {
emits: ['openDetail', "updateData"],
components: {
itemCompareQty,
recommend,
balanceQtyEdit,
winScanLocation
},
props: {
dataContent: {
type: Object,
default: null
},
settingParam: {
type: Object,
default: null
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowLocation: {
type: Boolean,
default: true
},
locationAreaTypeList: {
type: Array,
default: null
},
},
watch: {
dataContent: {
handler(newName, oldName) {
if (this.dataContent.subList.length > 0) {
if (this.$refs.collapse1 != undefined && this.$refs.collapse1 != null) {
this.$nextTick(res => {
this.$refs.collapse1.resize()
})
}
}
},
immediate: true,
deep: true
}
},
data() {
return {
option: [],
showItem: {},
locatonItem: {},
editItem: {},
detailOptions: [],
scanOptions: []
}
},
mounted() {
if (this.detailOptions.length == 0) {
this.detailOptions = getDetailOption();
}
if (this.scanOptions.length == 0) {
this.scanOptions = getPurchaseReceiptOption(this.settingParam.allowModifyQty, this.settingParam
.allowModifyLocation)
}
},
methods: {
swipeClick(e, item) {
if (e.content.text == "详情") {
this.detail(item)
} else if (e.content.text == "编辑") {
this.edit(item)
} else if (e.content.text == "库位") {
this.showLocation(item)
} else if (e.content.text == "移除") {
this.remove(item)
}
},
edit(item) {
this.editItem = item;
this.$refs.qtyEdit.openEditPopup(item.balance, item.handleQty);
},
detail(item) {
this.$emit('openDetail', item);
// this.showItem = item;
// this.$refs.jobDetailPopup.openPopup(item)
},
remove(item) {
this.$refs.message.showQuestionMessage("确定移除扫描信息?",
res => {
if (res) {
item.scaned = false
item.balance = {}
item.handleQty = null;
this.$forceUpdate()
this.$emit('remove', item)
}
});
},
confirm(qty) {
this.editItem.handleQty = qty;
this.$emit('updateData')
},
showLocation(item) {
this.locatonItem = item;
this.$refs.scanLocationCode.openScanPopup();
},
//
getLocation(location, code) {
this.locatonItem.toLocationCode = code;
this.$emit('updateData')
},
}
}
</script>
<style>
</style>

161
src/mycomponents/detail/comJobDetailCard.vue

@ -0,0 +1,161 @@
<template>
<view class="" style="background-color: #fff;">
<uni-collapse ref="collapse" style="height: 500px;">
<uni-collapse-item :open="true">
<template v-slot:title>
<itemCompareQty :dataContent="dataContent" :handleQty="dataContent.handleQty"
:isShowPackUnit="false"></itemCompareQty>
</template>
<package-list :dataContent="dataContent.subList"
:isEdit="settingParam.allowModifyQty=='TRUE'"
:settingParam="settingParam"
@collapseChange="collapseChange"
@updateData="updateData"
></package-list>
</uni-collapse-item>
</uni-collapse>
<recommend-qty-edit ref=" receiptEdit" :dataContent="editItem" :settingParam="settingParam" @confirm="confirm">
</recommend-qty-edit>
<comMessage ref="message"></comMessage>
</view>
</template>
<script>
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue'
import recommend from '@/mycomponents/recommend/recommend.vue'
import recommendQtyEdit from '@/mycomponents/qty/recommendQtyEdit.vue'
import jobDetailPopup from '@/mycomponents/detail/jobDetailPopup.vue'
import receiptDetailInfoPopup from '@/pages/purchaseReceipt/coms/receiptDetailInfoPopup.vue'
import pack from '@/mycomponents/balance/pack.vue'
import detailList from '@/mycomponents/detail/detailList.vue'
import packageList from '@/mycomponents/package/packageList.vue'
import {
getDetailOption,
getPurchaseReceiptOption
} from '@/common/array.js';
export default {
emits: ["updateData"],
components: {
itemCompareQty,
recommend,
recommendQtyEdit,
jobDetailPopup,
receiptDetailInfoPopup,
detailList,
packageList
},
props: {
dataContent: {
type: Object,
default: null
},
settingParam: {
type: Object,
default: null
},
locationAreaTypeList: {
type: Object,
default: null
},
},
watch: {
},
data() {
return {
showItem: {},
editItem: {
record: {
}
},
locatonItem: {},
detailOptions: [],
scanOptions: []
}
},
mounted() {
if (this.detailOptions.length == 0) {
this.detailOptions = getDetailOption();
}
if (this.scanOptions.length == 0) {
this.scanOptions = getPurchaseReceiptOption(this.settingParam.allowModifyQty, this.settingParam
.allowModifyLocation)
}
},
updated() {
console.log('updated')
},
methods: {
collapseChange(){
setTimeout(() => {
this.resizeCollapse();
}, 500)
},
resizeCollapse() {
this.$nextTick(r => {
this.$refs.collapse.resize()
});
this.$forceUpdate();
},
refreshCollapse() {
this.$nextTick(r => {
this.$refs.collapse.forEach(r => {
r.childrens.forEach(i => {
i.init();
})
r.resize();
})
});
this.$forceUpdate();
},
swipeClick(e, item) {
if (e.content.text == "编辑") {
this.edit(item)
} else if (e.content.text == "移除") {
this.remove(item)
}
},
edit(item) {
this.editItem = item;
this.$refs.receiptEdit.openTaskEditPopup(item.qty, item.handleQty, item.labelQty);
},
remove(item) {
this.$refs.message.showQuestionMessage("确定移除扫描信息?",
res => {
if (res) {
item.scaned = false
item.handleQty = null
this.$forceUpdate()
this.$emit('remove', item)
}
});
},
confirm(qty) {
this.editItem.handleQty = qty;
this.$emit('updateData')
},
updateData(){
this.$emit('updateData')
}
}
}
</script>
<style>
</style>

151
src/mycomponents/detail/comRequestDetailCard.vue

@ -0,0 +1,151 @@
<template>
<view class="" style="background-color: #fff;">
<!-- <comReturnRequestInfo :workShopCode="dataContent.workshopCode" :dataContent="requestItem">
</comReturnRequestInfo> -->
<uni-collapse ref="collapse1" @change="">
<uni-collapse-item :open="true">
<template v-slot:title>
<item-compare-qty
:dataContent="dataContent"
:handleQty="Number(dataContent.handleQty)"
:isShowStdPack="false">
</item-compare-qty>
</template>
<u-line />
<view class="" v-for="(item,index) in dataContent.subList">
<uni-swipe-action ref="swipeAction">
<uni-swipe-action-item @click="swipeClick($event,item)"
:right-options="item.scaned?scanOptions:detailOptions">
<recommend :detail="item" :record="item.record" :isShowPack="isShowPack"
:isShowBatch="isShowBatch" :isShowFromLocation="isShowLocation"></recommend>
</uni-swipe-action-item>
</uni-swipe-action>
</view>
</uni-collapse-item>
</uni-collapse>
<balance-qty-edit ref="qtyEdit" :settingParam="settingParam" @confirm="confirm"></balance-qty-edit>
<comMessage ref="message"></comMessage>
</view>
</template>
<script>
import itemCompareQty from '@/mycomponents/item/itemCompareQty.vue'
import recommend from '@/mycomponents/recommend/recommend.vue'
import balanceQtyEdit from '@/mycomponents/qty/balanceQtyEdit.vue'
import comReturnRequestInfo from '@/pages/productionReturn/coms/comReturnRequestInfo.vue'
import {
getDetailOption,
getDetailEditRemoveOption,
getDetailRemoveOption
} from '@/common/array.js';
export default {
emits: ['openDetail'],
components: {
itemCompareQty,
recommend,
balanceQtyEdit,
comReturnRequestInfo
},
props: {
dataContent: {
type: Object,
default: {}
},
settingParam: {
type: Object,
default: {}
},
isShowPack: {
type: Boolean,
default: true
},
isShowBatch: {
type: Boolean,
default: true
},
isShowLocation: {
type: Boolean,
default: true
},
},
watch: {
dataContent(newVal) {
var test =this.dataContent
this.requestItem = newVal.subList[0];
},
},
data() {
return {
option: [],
showItem: {},
editItem: {
record: {
}
},
detailOptions: [],
scanOptions: [],
requestItem:{}
}
},
mounted() {
if (this.detailOptions.length == 0) {
this.detailOptions = getDetailOption();
}
if (this.scanOptions.length == 0) {
this.scanOptions = getDetailEditRemoveOption();
// if (this.dataContent.allowModifyQty == 1) {
// this.scanOptions = getDetailEditRemoveOption();
// } else {
// this.scanOptions = getDetailRemoveOption();
// }
}
},
methods: {
swipeClick(e, item) {
if (e.content.text == "详情") {
this.detail(item)
} else if (e.content.text == "编辑") {
this.edit(item)
} else if (e.content.text == "移除") {
this.remove(item)
}
},
edit(item) {
this.editItem = item;
this.$refs.qtyEdit.openEditPopup(item.balance, item.record.qty);
},
detail(item) {
this.$emit('openDetail', item);
// this.showItem = item;
// this.$refs.jobDetailPopup.openPopup(item)
},
remove(item) {
this.$refs.message.showQuestionMessage("确定移除扫描信息?",
res => {
if (res) {
item.scaned = false
item.record = {}
item.balance = {}
item.inventoryStatus = item.RecommendInventoryStatus
// item.record.qty = 0;
this.$forceUpdate()
this.$emit('remove', item)
}
});
},
confirm(qty) {
this.editItem.record.qty = qty;
this.$emit('updateData')
}
}
}
</script>
<style>
</style>

67
src/mycomponents/detail/detailBalanceInfo.vue

@ -0,0 +1,67 @@
<template>
<view>
<!-- <view class="item_big_title">
[明细]
</view> -->
<view class="item">
<text class="item_title">箱码 : </text>
<text class="text_wrap">{{dataContent.packingNumber}}</text>
</view>
<view class="item">
<text class="item_title">批次 : </text>
<text class="text_wrap">{{dataContent.batch}}</text>
</view>
<view class="item">
<text class="item_title">数量 : </text>
<view class="text_wrap">
<text class="text_wrap">{{Number(dataContent.qty)}}</text>
<text class="text_wrap">{{getUomInfo(dataContent.uom)}}</text>
</view>
</view>
<view class="item">
<text class="item_title">库存状态 : </text>
<text class="text_wrap">{{getInventoryStatusInfo(dataContent.inventoryStatus)}}</text>
</view>
<view class="item">
<text class="item_title">来源库位 : </text>
<text class="text_wrap">{{dataContent.fromLocationCode}}</text>
</view>
</view>
</template>
<script>
import {
getInventoryStatusName,
getPackUnitInfo,
getUomInfo
} from '@/common/directory.js';
export default {
components: {},
data() {
return {
}
},
mounted() {},
props: {
dataContent: {
type: Object,
default: {}
}
},
methods: {
getInventoryStatusInfo(value) {
return getInventoryStatusName(value)
},
getUomInfo(value){
return getUomInfo(value).label
}
}
}
</script>
<style>
</style>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save