lijuncheng
10 months ago
885 changed files with 152200 additions and 90 deletions
@ -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? |
@ -0,0 +1,4 @@ |
|||
{ |
|||
"rootPathIndex": 1, |
|||
"webRoot": "${projectDir}" |
|||
} |
@ -0,0 +1,24 @@ |
|||
{ |
|||
// launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/ |
|||
// launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数 |
|||
"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" |
|||
} |
|||
] |
|||
} |
@ -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 |
@ -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> |
@ -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; |
|||
} |
|||
} |
|||
} |
File diff suppressed because it is too large
@ -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" |
|||
} |
|||
} |
@ -0,0 +1,2 @@ |
|||
别名:testalias |
|||
密码: wms3.0 |
@ -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 { |
|||
|
|||
} |
|||
} |
@ -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> |
@ -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; |
File diff suppressed because it is too large
@ -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 |
|||
}); |
|||
} |
|||
|
|||
} |
@ -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 |
|||
} |
@ -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) |
|||
}) |
|||
} |
File diff suppressed because it is too large
@ -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(); |
@ -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, |
|||
}, |
|||
|
|||
] |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
] |
@ -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; |
|||
} |
@ -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 |
@ -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); |
|||
} |
@ -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) |
|||
}) |
|||
} |
@ -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; |
|||
|
|||
} |
|||
} |
File diff suppressed because it is too large
@ -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; |
|||
|
|||
} |
File diff suppressed because it is too large
@ -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) |
|||
} |
@ -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 |
|||
} |
@ -0,0 +1,9 @@ |
|||
const constant = { |
|||
avatar: 'vuex_avatar', |
|||
name: 'vuex_name', |
|||
roles: 'vuex_roles', |
|||
permissions: 'vuex_permissions', |
|||
tenantId:'vuex_tenantId' |
|||
} |
|||
|
|||
export default constant |
@ -0,0 +1,6 @@ |
|||
export default { |
|||
'401': '认证失败,无法访问系统资源', |
|||
'403': '当前操作没有权限', |
|||
'404': '访问资源不存在', |
|||
'default': '系统未知错误,请反馈给管理员' |
|||
} |
@ -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 |
|||
} |
|||
} |
@ -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 |
|||
} |
@ -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 |
|||
} |
@ -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; |
|||
} |
|||
|
@ -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) |
|||
}, |
|||
//提取表单key和value |
|||
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() |
|||
}, |
|||
// 帮我更具 参数 date为日期选择,time为时间选择,year-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> |
@ -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) |
|||
}, |
|||
//提取表单key和value |
|||
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() |
|||
}, |
|||
// 帮我更具 参数 date为日期选择,time为时间选择,year-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> |
@ -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 = |
|||
} |
|||
} |
|||
} |
|||
|
|||
``` |
@ -0,0 +1,15 @@ |
|||
export default { |
|||
data() { |
|||
return {} |
|||
}, |
|||
methods: { |
|||
// 微信小程序获取手机号
|
|||
async getphonenumber({detail}) { |
|||
|
|||
}, |
|||
// 获取验证码回调 此处调用api接口 并赋值
|
|||
async sendCodeCallback(item) { |
|||
// item.rules.value =
|
|||
} |
|||
} |
|||
} |
@ -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 = |
|||
} |
|||
} |
|||
} |
|||
|
|||
``` |
@ -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> |
@ -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> |
@ -0,0 +1,15 @@ |
|||
export default { |
|||
data() { |
|||
return {} |
|||
}, |
|||
methods: { |
|||
// 微信小程序获取手机号
|
|||
async getphonenumber({detail}) { |
|||
|
|||
}, |
|||
// 获取验证码回调 此处调用api接口 并赋值
|
|||
async sendCodeCallback(item) { |
|||
// item.rules.value =
|
|||
} |
|||
} |
|||
} |
@ -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; |
File diff suppressed because one or more lines are too long
@ -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> |
@ -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() { |
|||
// 这里可以做i18n国际化相关操作,可以通过uni.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> |
@ -0,0 +1 @@ |
|||
export default './lib/marked' |
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
@ -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; |
@ -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> |
@ -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> |
@ -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, |
|||
}); |
|||
}; |
|||
}); |
|||
} |
|||
} |
@ -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> |
@ -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; |
@ -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> |
@ -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-model所绑定的list的值 |
|||
value: { |
|||
type: Array, |
|||
default: function() { |
|||
return []; |
|||
} |
|||
}, |
|||
//是否使用虚拟列表,默认为否 |
|||
useVirtualList: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
//是否在z-paging内部循环渲染列表(内置列表),默认为否。若use-virtual-list为true,则此项恒为true |
|||
useInnerList: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
//内置列表cell的key名称,仅nvue有效,在nvue中开启use-inner-list时必须填此项 |
|||
cellKeyName: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
//innerList样式 |
|||
innerListStyle: { |
|||
type: Object, |
|||
default: function() { |
|||
return {}; |
|||
} |
|||
}, |
|||
//预加载的列表可视范围(列表高度)页数,默认为12,即预加载当前页及上下各7页的cell。此数值越大,则虚拟列表中加载的dom越多,内存消耗越大(会维持在一个稳定值),但增加预加载页面数量可缓解快速滚动短暂白屏问题 |
|||
preloadPage: { |
|||
type: [Number, String], |
|||
default: 12 |
|||
}, |
|||
//虚拟列表cell高度模式,默认为fixed,也就是每个cell高度完全相同,将以第一个cell高度为准进行计算。可选值【dynamic】,即代表高度是动态非固定的,【dynamic】性能低于【fixed】。 |
|||
cellHeightMode: { |
|||
type: String, |
|||
default: 'fixed' |
|||
}, |
|||
//虚拟列表scroll取样帧率,默认为60,过高可能出现卡顿等问题 |
|||
virtualScrollFps: { |
|||
type: [Number, String], |
|||
default: 60 |
|||
}, |
|||
}, |
|||
watch: { |
|||
//监听页面v-mode传过来的值,同时传给z-paging |
|||
value(newVal) { |
|||
this.list = newVal; |
|||
}, |
|||
// #ifdef VUE3 |
|||
modelValue(newVal) { |
|||
this.list = newVal; |
|||
}, |
|||
// #endif |
|||
//监听z-paging给当前组件的值,同时传给页面 |
|||
list(newVal) { |
|||
//通过emit input修改页面中v-model绑定的值 |
|||
this.$emit('input', newVal); |
|||
// #ifdef VUE3 |
|||
this.$emit('update:modelValue', newVal); |
|||
// #endif |
|||
} |
|||
}, |
|||
methods: { |
|||
//监听z-paging的@query方法,通过emit传递给页面 |
|||
queryList(pageNo, pageSize) { |
|||
console.log("queryList",pageNo) |
|||
// this.$emit('query', pageNo, pageSize); |
|||
}, |
|||
//接收页面触发的reload方法,传给z-paging |
|||
reload(data) { |
|||
this.$refs.paging.reload(data); |
|||
}, |
|||
//接收页面触发的complete方法,传给z-paging |
|||
complete(data) { |
|||
this.$refs.paging.complete(data); |
|||
}, |
|||
/* |
|||
//如果是使用页面滚动,则需要添加以下三行,注意页面那边要引入mixins,与使用页面滚动示例写法相同。 |
|||
//接收页面触发的updatePageScrollTop方法,传给z-paging |
|||
updatePageScrollTop(data){ |
|||
this.$refs.paging.updatePageScrollTop(data); |
|||
}, |
|||
//接收页面触发的pageReachBottom方法,传给z-paging |
|||
pageReachBottom(){ |
|||
this.$refs.paging.pageReachBottom(); |
|||
}, |
|||
//接收页面触发的doChatRecordLoadMore方法,传给z-paging |
|||
doChatRecordLoadMore() { |
|||
this.$refs.paging.doChatRecordLoadMore(); |
|||
} |
|||
*/ |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
|
|||
</style> |
@ -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> |
@ -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> |
@ -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或者"",否则后续将current赋值为0, |
|||
// 无能的TX没有使用===而是使用==判断,导致程序认为前后二者没有变化,从而不会触发视图更新 |
|||
current: 99999, |
|||
// 外层内容的样式,初始时处于底层,且透明 |
|||
contentStyle: { |
|||
// zIndex: 11, |
|||
zIndex: -1, |
|||
opacity: 0 |
|||
}, |
|||
// 让某个菜单保持高亮的状态 |
|||
highlightIndex: 99999, |
|||
contentHeight: 0 |
|||
} |
|||
}, |
|||
computed: { |
|||
// 下拉出来部分的样式 |
|||
popupStyle() { |
|||
let style = {}; |
|||
// 进行Y轴位移,展开状态时,恢复原位。收齐状态时,往上位移100%,进行隐藏 |
|||
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)的this,不能在data中声明变量,否则在微信小程序会造成循环引用而报错 |
|||
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: none,是因为nvue没有display这个属性 |
|||
|
|||
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 => { |
|||
// 这里获取的是dropdown的尺寸,在H5上,uniapp获取尺寸是有bug的(以前提出修复过,后来又出现了此bug,目前hx2.8.11版本) |
|||
// H5端bug表现为元素尺寸的top值为导航栏底部到到元素的上边沿的距离,但是元素的bottom值确是导航栏顶部到元素底部的距离 |
|||
// 二者是互相矛盾的,本质原因是H5端导航栏非原生,uni的开发者大意造成 |
|||
// 这里取菜单栏的botton值合理的,不能用res.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> |
@ -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> |
@ -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> |
File diff suppressed because it is too large
@ -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 |
|||
} |
@ -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 |
|||
}; |
|||
} |
@ -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 //true表示忽略版本检查提示框,HBuilderX1.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" |
|||
} |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -0,0 +1,25 @@ |
|||
<template> |
|||
<view class="batch_view"> |
|||
<text class="card_batch">批次</text> |
|||
<text class="card_batch_content"> {{batch}}</text> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
data(){ |
|||
return { |
|||
} |
|||
}, |
|||
props: { |
|||
batch:{ |
|||
type: String, |
|||
default: "" |
|||
} |
|||
}, |
|||
|
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
</style> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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 指定要获取摄像头的索引值,1表示主摄像头,2表示辅摄像头。如果没有设置则使用系统默认主摄像头。 |
|||
// // 安卓不能默认打开前置摄像头 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> |
@ -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> |
@ -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> |
@ -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> |
@ -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">  请扫描</text> |
|||
<text style="color:#3FBAFF; font-size: 35rpx;">  {{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> |
@ -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> |
@ -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> |
@ -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> |
@ -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…
Reference in new issue