@ -0,0 +1,36 @@ |
|||
'use strict'; |
|||
|
|||
const { simpleExcelDown } = require('../../../../utils/xlsxDownload'); |
|||
|
|||
async function dataExport (ctx) { |
|||
try { |
|||
// const models = ctx.fs.dc.models;
|
|||
// const { userId } = ctx.fs.api
|
|||
// const { ids } = ctx.query;
|
|||
|
|||
// const exportData = await models.BusCar.destroy({
|
|||
// where: {
|
|||
// id: { $in: ids.split(',') }
|
|||
// }
|
|||
// })
|
|||
|
|||
// const fileName = `摄像头信息列表_${userId}_${moment().format('YYYYMMDDHHmmss')}` + '.csv'
|
|||
// const filePath = await simpleExcelDown({ data: exportData, header, fileName: fileName })
|
|||
// const fileData = fs.readFileSync(filePath);
|
|||
|
|||
// ctx.status = 200;
|
|||
// ctx.set('Content-Type', 'application/x-xls');
|
|||
// ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName));
|
|||
// ctx.body = fileData;
|
|||
} catch (error) { |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = { |
|||
message: typeof error == 'string' ? error : undefined |
|||
} |
|||
} |
|||
} |
|||
|
|||
module.exports = { |
|||
dataExport |
|||
}; |
@ -0,0 +1,77 @@ |
|||
'use strict'; |
|||
|
|||
async function publicityGet (ctx) { |
|||
try { |
|||
const models = ctx.fs.dc.models; |
|||
const { enable } = ctx.query; |
|||
let findOption = { |
|||
where: {}, |
|||
order: [['id', 'DESC']] |
|||
} |
|||
if (enable) { |
|||
findOption.where.enable = true |
|||
} |
|||
|
|||
const roadRes = await models.Publicity.findAll(findOption) |
|||
|
|||
ctx.status = 200; |
|||
ctx.body = roadRes |
|||
} catch (error) { |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = { |
|||
message: typeof error == 'string' ? error : undefined |
|||
} |
|||
} |
|||
} |
|||
|
|||
async function publicityEdit (ctx) { |
|||
try { |
|||
const models = ctx.fs.dc.models; |
|||
const data = ctx.request.body; |
|||
|
|||
if (!data.publicityId) { |
|||
await models.Publicity.create(data) |
|||
} else { |
|||
await models.Publicity.update( |
|||
data, { |
|||
where: { |
|||
id: data.publicityId |
|||
} |
|||
}) |
|||
} |
|||
|
|||
ctx.status = 204 |
|||
} catch (error) { |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = { |
|||
message: typeof error == 'string' ? error : undefined |
|||
} |
|||
} |
|||
} |
|||
|
|||
async function publicityDel (ctx) { |
|||
try { |
|||
const models = ctx.fs.dc.models; |
|||
const { publicityId } = ctx.params; |
|||
|
|||
await models.Publicity.destroy({ |
|||
where: { |
|||
id: publicityId |
|||
} |
|||
}) |
|||
|
|||
ctx.status = 204 |
|||
} catch (error) { |
|||
ctx.fs.logger.error(`path: ${ctx.path}, error: ${error}`); |
|||
ctx.status = 400; |
|||
ctx.body = { |
|||
message: typeof error == 'string' ? error : undefined |
|||
} |
|||
} |
|||
} |
|||
|
|||
module.exports = { |
|||
publicityGet, publicityEdit, publicityDel, |
|||
}; |
@ -0,0 +1,52 @@ |
|||
/* eslint-disable*/ |
|||
'use strict'; |
|||
|
|||
module.exports = dc => { |
|||
const DataTypes = dc.ORM; |
|||
const sequelize = dc.orm; |
|||
const Publicity = sequelize.define("publicity", { |
|||
id: { |
|||
type: DataTypes.INTEGER, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: true, |
|||
field: "id", |
|||
autoIncrement: true, |
|||
unique: "publicity_id_uindex" |
|||
}, |
|||
name: { |
|||
type: DataTypes.STRING, |
|||
allowNull: false, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "name", |
|||
autoIncrement: false |
|||
}, |
|||
video: { |
|||
type: DataTypes.ARRAY(DataTypes.INTEGER), |
|||
allowNull: true, |
|||
defaultValue: null, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "video", |
|||
autoIncrement: false |
|||
}, |
|||
enable: { |
|||
type: DataTypes.BOOLEAN, |
|||
allowNull: false, |
|||
defaultValue: true, |
|||
comment: null, |
|||
primaryKey: false, |
|||
field: "enable", |
|||
autoIncrement: false |
|||
} |
|||
}, { |
|||
tableName: "publicity", |
|||
comment: "", |
|||
indexes: [] |
|||
}); |
|||
dc.models.Publicity = Publicity; |
|||
return Publicity; |
|||
}; |
@ -0,0 +1,77 @@ |
|||
'use strict'; |
|||
const fs = require('fs'); |
|||
const xlsx = require('better-xlsx'); |
|||
const path = require('path') |
|||
const moment = require('moment') |
|||
|
|||
//递归创建目录 同步方法
|
|||
async function makeDir (dir) { |
|||
if (!fs.existsSync(dir)) { |
|||
makeDir(path.dirname(dir)) |
|||
fs.mkdirSync(dir, function (err) { |
|||
if (err) { |
|||
throw err |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
async function simpleExcelDown ({ data = [], header = [], fileName = moment().format('YYYY-MM-DD HH:mm:ss') } = {}) { |
|||
const fileDirPath = path.join(__dirname, `../../downloadFiles`) |
|||
makeDir(fileDirPath) |
|||
const file = new xlsx.File(); |
|||
const sheet_1 = file.addSheet('sheet_1'); |
|||
|
|||
// header
|
|||
const headerStyle = new xlsx.Style(); |
|||
headerStyle.align.h = 'center'; |
|||
headerStyle.align.v = 'center'; |
|||
headerStyle.border.right = 'thin'; |
|||
headerStyle.border.rightColor = '#000000'; |
|||
headerStyle.border.bottom = 'thin'; |
|||
headerStyle.border.bottomColor = '#000000'; |
|||
|
|||
const headerRow = sheet_1.addRow(); |
|||
const indexCell = headerRow.addCell(); |
|||
indexCell.value = '序号' |
|||
indexCell.style = headerStyle |
|||
for (let h of header) { |
|||
const cell = headerRow.addCell(); |
|||
cell.value = h.title; |
|||
cell.style = headerStyle |
|||
} |
|||
|
|||
// data
|
|||
const style = new xlsx.Style(); |
|||
style.align.h = 'left'; |
|||
style.align.v = 'center'; |
|||
style.border.right = 'thin'; |
|||
style.border.rightColor = '#000000'; |
|||
style.border.bottom = 'thin'; |
|||
style.border.bottomColor = '#000000'; |
|||
for (let i = 0; i < data.length; i++) { |
|||
const row = sheet_1.addRow(); |
|||
const indexCell = row.addCell(); |
|||
indexCell.value = i + 1 |
|||
indexCell.style = headerStyle |
|||
for (let h of header) { |
|||
const cell = row.addCell(); |
|||
cell.value = data[i][h.key]; |
|||
cell.style = style |
|||
} |
|||
} |
|||
|
|||
const savePath = path.join(fileDirPath, fileName) |
|||
await new Promise(function (resolve, reject) { |
|||
file.saveAs() |
|||
.pipe(fs.createWriteStream(savePath)) |
|||
.on('finish', () => { |
|||
resolve() |
|||
}); |
|||
}) |
|||
return savePath |
|||
} |
|||
module.exports = { |
|||
simpleExcelDown, |
|||
makeDir |
|||
} |
@ -0,0 +1,19 @@ |
|||
pipeline { |
|||
agent { |
|||
node{ |
|||
label 'jnlp-slave' |
|||
} |
|||
} |
|||
|
|||
stages { |
|||
stage('Highways4Good Api ......') { |
|||
steps { |
|||
sh 'switch-auth.sh anxinyun' |
|||
buildName "#${BUILD_NUMBER} ~/fs-cloud/${JOB_NAME}:${IMAGE_VERSION}" |
|||
buildDescription "registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION}" |
|||
sh 'docker build -t registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION} ./api' |
|||
sh 'docker push registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION}' |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,19 @@ |
|||
pipeline { |
|||
agent { |
|||
node{ |
|||
label 'jnlp-slave' |
|||
} |
|||
} |
|||
|
|||
stages { |
|||
stage('Highways4Good Web......') { |
|||
steps { |
|||
sh 'switch-auth.sh anxinyun' |
|||
buildName "#${BUILD_NUMBER} ~/fs-cloud/${JOB_NAME}:${IMAGE_VERSION}" |
|||
buildDescription "registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION}" |
|||
sh 'docker build -t registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION} ./web' |
|||
sh 'docker push registry.cn-hangzhou.aliyuncs.com/${CLOUD}/${JOB_NAME}:${IMAGE_VERSION}' |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,17 @@ |
|||
{ |
|||
// 使用 IntelliSense 了解相关属性。 |
|||
// 悬停以查看现有属性的描述。 |
|||
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 |
|||
"version": "0.2.0", |
|||
"configurations": [ |
|||
{ |
|||
"type": "node", |
|||
"request": "launch", |
|||
"name": "启动程序", |
|||
"skipFiles": [ |
|||
"<node_internals>/**" |
|||
], |
|||
"program": "${workspaceFolder}\\index.js" |
|||
} |
|||
] |
|||
} |
After Width: | Height: | Size: 205 KiB |
After Width: | Height: | Size: 183 KiB |
After Width: | Height: | Size: 242 KiB |
After Width: | Height: | Size: 858 KiB |
After Width: | Height: | Size: 808 KiB |
After Width: | Height: | Size: 234 KiB |
After Width: | Height: | Size: 895 KiB |
After Width: | Height: | Size: 220 KiB |
After Width: | Height: | Size: 987 KiB |
After Width: | Height: | Size: 260 KiB |
After Width: | Height: | Size: 970 KiB |
After Width: | Height: | Size: 759 KiB |
After Width: | Height: | Size: 166 KiB |
After Width: | Height: | Size: 108 KiB |
After Width: | Height: | Size: 216 KiB |
After Width: | Height: | Size: 762 KiB |
After Width: | Height: | Size: 206 KiB |
After Width: | Height: | Size: 710 KiB |
After Width: | Height: | Size: 264 KiB |
After Width: | Height: | Size: 557 KiB |
After Width: | Height: | Size: 252 KiB |
After Width: | Height: | Size: 622 KiB |
After Width: | Height: | Size: 744 KiB |
After Width: | Height: | Size: 232 KiB |
After Width: | Height: | Size: 408 KiB |
After Width: | Height: | Size: 416 KiB |
After Width: | Height: | Size: 248 KiB |
After Width: | Height: | Size: 893 KiB |
After Width: | Height: | Size: 214 KiB |
After Width: | Height: | Size: 924 KiB |
After Width: | Height: | Size: 211 KiB |
After Width: | Height: | Size: 932 KiB |
After Width: | Height: | Size: 255 KiB |
After Width: | Height: | Size: 932 KiB |
After Width: | Height: | Size: 269 KiB |
After Width: | Height: | Size: 211 KiB |
After Width: | Height: | Size: 899 KiB |
After Width: | Height: | Size: 251 KiB |
After Width: | Height: | Size: 219 KiB |
After Width: | Height: | Size: 227 KiB |
After Width: | Height: | Size: 797 KiB |
After Width: | Height: | Size: 258 KiB |
After Width: | Height: | Size: 874 KiB |
After Width: | Height: | Size: 227 KiB |
After Width: | Height: | Size: 1008 KiB |
@ -0,0 +1,132 @@ |
|||
try { |
|||
const { Pool, Client } = require('pg') |
|||
const request = require('superagent'); |
|||
const Hex = require('crypto-js/enc-hex'); |
|||
const MD5 = require('crypto-js/md5'); |
|||
const XLSX = require('xlsx') |
|||
const path = require('path') |
|||
const fs = require("fs"); |
|||
const qiniu = require('qiniu'); |
|||
const uuidv4 = require('uuid/v4'); |
|||
|
|||
// 连接数据库
|
|||
const pool = new Pool({ |
|||
user: 'postgres', |
|||
host: '10.8.30.32', |
|||
database: 'highways4good', |
|||
password: '123', |
|||
port: 5432, |
|||
}) |
|||
// 7niu 验证
|
|||
const accessKey = 'XuDgkao6cL0HidoMAPnA5OB10Mc_Ew08mpIfRJK5' |
|||
const secretKey = 'yewcieZLzKZuDfig0wLZ9if9jKp2P_1jd3CMJPSa' |
|||
const bucket = 'dev-highways4good' |
|||
|
|||
|
|||
|
|||
const fun = async () => { |
|||
// note: we don't try/catch this because if connecting throws an exception
|
|||
// we don't need to dispose of the client (it will be undefined)
|
|||
const client = await pool.connect() |
|||
try { |
|||
await client.query('BEGIN') |
|||
|
|||
console.log(`开始`); |
|||
const upload7niu = |
|||
async (filePath, filename) => { |
|||
return new Promise((resolve, reject) => { |
|||
try { |
|||
const uploadPath = 'images' |
|||
// 7niu 鉴权
|
|||
const mac = new qiniu.auth.digest.Mac(accessKey, secretKey); |
|||
const config = { |
|||
scope: bucket, |
|||
// expires: 3600,
|
|||
returnBody: '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)"}' |
|||
} |
|||
var putPolicy = new qiniu.rs.PutPolicy(config); |
|||
var uploadToken = putPolicy.uploadToken(mac); |
|||
// 上传文件
|
|||
var formUploader = new qiniu.form_up.FormUploader(config); |
|||
var putExtra = new qiniu.form_up.PutExtra(); |
|||
let key = path.posix.join(uploadPath, uuidv4(), filename); |
|||
formUploader.putFile(uploadToken, key, filePath, putExtra, function (respErr, |
|||
respBody, respInfo) { |
|||
if (respErr) { |
|||
reject(respErr); |
|||
throw respErr; |
|||
} |
|||
if (respInfo.statusCode == 200) { |
|||
console.log(respBody); |
|||
let qnkey = respBody.key; |
|||
resolve({ key: qnkey, url: `${qnkey}` }); |
|||
} else { |
|||
console.log(respInfo.statusCode); |
|||
console.log(respBody); |
|||
reject(new Error('failed to upload.')); |
|||
} |
|||
}); |
|||
|
|||
} catch (err) { |
|||
reject(err); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
|
|||
// 读取数据文件
|
|||
let workbook = XLSX.readFile(path.join(__dirname, './data/work.xlsx')); |
|||
let firstSheetName = workbook.SheetNames[0]; |
|||
let worksheet = workbook.Sheets[firstSheetName]; |
|||
let res = XLSX.utils.sheet_to_json(worksheet, { |
|||
defval: '' |
|||
}); |
|||
// console.log(res);
|
|||
res.sort((a, b) => { return Date.parse(a['时间']) - Date.parse(b['时间']) }); |
|||
|
|||
// 读取全部图片
|
|||
let pic = []; |
|||
fs.readdirSync(path.join(__dirname, '/data/pic')).forEach((filename) => { |
|||
pic.push({ |
|||
path: `./data/pic/${filename}`, |
|||
name: filename |
|||
}) |
|||
}); |
|||
|
|||
for (let r of res) { |
|||
console.log(r); |
|||
let picList = pic.filter(p => { |
|||
const { name } = p |
|||
const no = name.split('-')[0] |
|||
return no == r['编号'] |
|||
}) |
|||
console.log(picList); |
|||
// 将图片上传至 7niu
|
|||
let upPicUrl = []; |
|||
for (let p of picList) { |
|||
const upRes = await upload7niu(path.join(__dirname, p.path), p.name) |
|||
console.log(upRes); |
|||
upPicUrl.push(upRes.url) |
|||
} |
|||
const roadSectionArr = r['路段'] ? r['路段'].split('至') : null |
|||
const roadSection = roadSectionArr && roadSectionArr.length > 1 ? roadSectionArr : [null, null] |
|||
await client.query(`INSERT INTO report (report_type, project_type, road, road_section_start, road_section_end,time,content,conserve_underway_pic) VALUES($1, $2, $3, $4, $5, $6, $7, $8) `, ['conserve', 'road', r['道路'], roadSection[0], roadSection[1], r['时间'], r['内容'], upPicUrl]) |
|||
// break
|
|||
} |
|||
|
|||
// await client.query('ROLLBACK')
|
|||
await client.query('COMMIT') |
|||
console.log('执行完毕~') |
|||
} catch (e) { |
|||
await client.query('ROLLBACK') |
|||
console.log('执行错误~') |
|||
throw e |
|||
} finally { |
|||
client.release(); |
|||
} |
|||
} |
|||
|
|||
fun() |
|||
} catch (error) { |
|||
console.error(error) |
|||
} |
@ -0,0 +1,20 @@ |
|||
{ |
|||
"name": "appkey-generator", |
|||
"version": "1.0.0", |
|||
"description": "tool", |
|||
"main": "index.js", |
|||
"scripts": { |
|||
"test": "mocha", |
|||
"start": "set NODE_ENV=development&&node index" |
|||
}, |
|||
"author": "liu", |
|||
"license": "ISC", |
|||
"dependencies": { |
|||
"crypto-js": "^4.1.1", |
|||
"pg": "^7.18.2", |
|||
"qiniu": "^7.7.0", |
|||
"superagent": "^8.0.0", |
|||
"uuid": "3.1.0", |
|||
"xlsx": "^0.17.1" |
|||
} |
|||
} |
@ -0,0 +1,3 @@ |
|||
export default { |
|||
navigationBarTitleText: '修改密码' |
|||
} |
@ -0,0 +1,64 @@ |
|||
import React, { useState } from 'react' |
|||
import Taro from '@tarojs/taro' |
|||
import { View, Input } from '@tarojs/components' |
|||
import { AtButton } from 'taro-ui' |
|||
import request from '@/services/request' |
|||
import { putPassword } from '@/services/api' |
|||
import './index.scss' |
|||
|
|||
function Index() { |
|||
const userInfo = Taro.getStorageSync('userInfo') || null; |
|||
const [phone, setPhone] = useState(userInfo.phone) |
|||
const [password, setPassword] = useState('') |
|||
const [password2, setPassword2] = useState('') |
|||
|
|||
function confirm() { |
|||
if (!password) { |
|||
Taro.showToast({ title: '请输入密码' }) |
|||
return |
|||
} else if (password !== password2) { |
|||
Taro.showToast({ title: '两次输入的密码不一致' }) |
|||
return |
|||
} else { |
|||
Taro.showModal({ |
|||
title: '提示', |
|||
content: '确定修改吗', |
|||
success: function (res) { |
|||
if (res.confirm) { |
|||
Taro.showLoading({ |
|||
title: '修改中' |
|||
}) |
|||
request.put(putPassword(userInfo.id), { password }).then(res => { |
|||
Taro.hideLoading() |
|||
if (res.statusCode == 200 || res.statusCode == 204) { |
|||
Taro.removeStorageSync('token') |
|||
Taro.removeStorageSync('userInfo') |
|||
Taro.reLaunch({ url: '/packages/changePassword/success/index' }) |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
}) |
|||
} |
|||
} |
|||
|
|||
return ( |
|||
<View className='page'> |
|||
<View className='phone'> |
|||
<View className='title'>手机号码:</View> |
|||
<Input value={phone} disabled={true} /> |
|||
</View> |
|||
<View className='pswd'> |
|||
<View className='title'>新的密码:</View> |
|||
<Input value={password} onInput={e => setPassword(e.detail.value)} /> |
|||
</View> |
|||
<View className='pswd'> |
|||
<View className='title'>再次输入新的密码:</View> |
|||
<Input value={password2} onInput={e => setPassword2(e.detail.value)} /> |
|||
</View> |
|||
<AtButton className='btn' type='primary' onClick={confirm}>确认</AtButton> |
|||
</View> |
|||
) |
|||
} |
|||
|
|||
export default Index |
@ -0,0 +1,35 @@ |
|||
page { |
|||
background-color: #f6f6f6; |
|||
font-size: 28px; |
|||
|
|||
.phone { |
|||
height: 96px; |
|||
background-color: #fff; |
|||
margin: 20px auto; |
|||
display: flex; |
|||
justify-content: left; |
|||
align-items: center; |
|||
|
|||
.title { |
|||
margin-left: 30px; |
|||
} |
|||
} |
|||
|
|||
.pswd { |
|||
height: 96px; |
|||
background-color: #fff; |
|||
margin-bottom: 5px; |
|||
display: flex; |
|||
justify-content: left; |
|||
align-items: center; |
|||
|
|||
.title { |
|||
margin-left: 30px; |
|||
} |
|||
} |
|||
|
|||
.btn { |
|||
width: 70%; |
|||
margin: 80px auto; |
|||
} |
|||
} |
@ -0,0 +1,3 @@ |
|||
export default { |
|||
navigationBarTitleText: '修改密码' |
|||
} |
@ -0,0 +1,24 @@ |
|||
import React from 'react' |
|||
import Taro from '@tarojs/taro' |
|||
import { View, Image } from '@tarojs/components' |
|||
import { AtButton } from 'taro-ui' |
|||
import './index.scss' |
|||
import successIcon from '../../../static/img/changePassword/success.svg' |
|||
|
|||
function Index() { |
|||
function handleClick() { |
|||
Taro.reLaunch({ url: '/pages/auth/login/login' }) |
|||
} |
|||
|
|||
return ( |
|||
<View> |
|||
<View className='box'> |
|||
<Image className='img' src={successIcon} /> |
|||
<View className='text'>修改成功!</View> |
|||
</View> |
|||
<AtButton className='btn' type='primary' onClick={handleClick}>返回登录</AtButton> |
|||
</View> |
|||
) |
|||
} |
|||
|
|||
export default Index |
@ -0,0 +1,26 @@ |
|||
page { |
|||
background-color: #f6f6f6; |
|||
|
|||
.box { |
|||
background-color: #fff; |
|||
height: 360px; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: center; |
|||
align-items: center; |
|||
|
|||
.img { |
|||
width: 160px; |
|||
height: 160px; |
|||
} |
|||
|
|||
.text { |
|||
margin-top: 32px; |
|||
} |
|||
} |
|||
|
|||
.btn { |
|||
width: 70%; |
|||
margin: 80px auto; |
|||
} |
|||
} |
@ -0,0 +1,52 @@ |
|||
/* |
|||
* 输入框筛选选择器 |
|||
*/ |
|||
import React, { useState, useEffect } from 'react' |
|||
import { View, Picker, Image, Input, Text } from '@tarojs/components' |
|||
import arrowIcon from '../../../static/img/patrol/arrow-down.svg' |
|||
import './index.scss' |
|||
|
|||
export default function InputPicker(props) { |
|||
const { title, placeholder, selector, value, onInput, isView } = props |
|||
const [curSelector, setCurSelector] = useState([]) |
|||
|
|||
useEffect(() => { |
|||
setCurSelector(selector) |
|||
}, []) |
|||
|
|||
function handleInput({ detail: { value: v } }) { |
|||
onInput(v) |
|||
if (v) { |
|||
setCurSelector(selector.filter(item => item && item.includes(v))) |
|||
} else { |
|||
setCurSelector(selector) |
|||
} |
|||
} |
|||
|
|||
const handlePickerChange = (e) => { |
|||
onInput(curSelector[e.detail.value]) |
|||
} |
|||
|
|||
return ( |
|||
<View className='input-picker'> |
|||
<View className='input-box'> |
|||
<View className='title'><Text style={{ color: 'red' }}>* </Text>{title}</View> |
|||
<Input |
|||
className='input' |
|||
type='text' |
|||
placeholder={placeholder} |
|||
border={false} |
|||
value={value} |
|||
onInput={handleInput} |
|||
disabled={isView} |
|||
/> |
|||
</View> |
|||
{ |
|||
!isView && |
|||
<Picker mode='selector' range={curSelector} onChange={handlePickerChange}> |
|||
<Image src={arrowIcon} className='img' /> |
|||
</Picker> |
|||
} |
|||
</View> |
|||
) |
|||
} |
@ -0,0 +1,30 @@ |
|||
.input-picker { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
height: 96px; |
|||
align-items: center; |
|||
background-color: #fff; |
|||
margin-bottom: 5px; |
|||
|
|||
.input-box { |
|||
padding: 12px 0; |
|||
flex-grow: 1; |
|||
display: flex; |
|||
align-items: center; |
|||
|
|||
.title { |
|||
margin-left: 12px; |
|||
} |
|||
|
|||
.input { |
|||
margin-left: 20px; |
|||
flex-grow: 1; |
|||
} |
|||
} |
|||
|
|||
.img { |
|||
width: 24px; |
|||
height: 14px; |
|||
margin: 0 30px; |
|||
} |
|||
} |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 623 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 15 KiB |
@ -1,37 +1,33 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="UTF-8" /> |
|||
<title></title> |
|||
<link rel="shortcut icon" href="/assets/images/favicon.ico" /> |
|||
<link |
|||
rel="stylesheet" |
|||
type="text/css" |
|||
href="/assets/font_sc/iconfont.css" |
|||
/> |
|||
<link rel="stylesheet" href="/assets/fontziti/font.css" /> |
|||
</head> |
|||
<body> |
|||
<link |
|||
rel="stylesheet/less" |
|||
type="text/css" |
|||
href="/assets/color.less" |
|||
rel="external nofollow" |
|||
/> |
|||
<script> |
|||
window.less = { |
|||
async: false, |
|||
env: "production", |
|||
}; |
|||
</script> |
|||
<script |
|||
type="text/javascript" |
|||
src="https://cdnjs.cloudflare.com/ajax/libs/less.js/2.7.2/less.min.js" |
|||
></script> |
|||
<div id="App"></div> |
|||
<script |
|||
type="text/javascript" |
|||
src="http://localhost:5001/client/build/app.js" |
|||
></script> |
|||
</body> |
|||
</html> |
|||
|
|||
<head> |
|||
<meta charset="UTF-8" /> |
|||
<title></title> |
|||
<link rel="shortcut icon" href="/assets/images/favicon.ico" /> |
|||
<link rel="stylesheet" type="text/css" href="/assets/font_sc/iconfont.css" /> |
|||
<link rel="stylesheet" href="/assets/fontziti/font.css" /> |
|||
<script type="text/javascript"> |
|||
window._AMapSecurityConfig = { |
|||
securityJsCode: 'e955cd5ddfc3a752aa27d1e1c67d182d', |
|||
} |
|||
</script> |
|||
<script |
|||
src="https://webapi.amap.com/maps?v=2.0&key=00f9a29dedcdbd8befec3dfe0cef5003&plugin=AMap.Adaptor,AMap.Scale,AMap.ToolBar,AMap.DistrictSearch,AMap.Geocoder,AMap.CustomLayer,Map3D,ElasticMarker"></script> |
|||
<script src="https://webapi.amap.com/loca?v=2.0.0&key=00f9a29dedcdbd8befec3dfe0cef5003"></script> |
|||
</head> |
|||
|
|||
<body> |
|||
<link rel="stylesheet/less" type="text/css" href="/assets/color.less" rel="external nofollow" /> |
|||
<script> |
|||
window.less = { |
|||
async: false, |
|||
env: "production", |
|||
}; |
|||
</script> |
|||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/less.js/2.7.2/less.min.js"></script> |
|||
<div id="App"></div> |
|||
<script type="text/javascript" src="http://localhost:5001/client/build/app.js"></script> |
|||
</body> |
|||
|
|||
</html> |