This commit is contained in:
曹辉 2023-03-03 10:04:13 +08:00
parent 1372c247d8
commit c00453f273
10 changed files with 1442 additions and 70 deletions

View File

@ -18,10 +18,18 @@ export function selectPatientSignIn(patientId) {
} }
//可兑换商品 //可兑换商品
export function selectExchangeGoods(pageNum, pageSize) {
export function selectExchangeGoods(pageNum,pageSize) {
return request({ return request({
url: `/nurseApplet/patientInfo/selectExchangeGoods?pageNum=${pageNum}&pageSize=${pageSize}`, url: `/nurseApplet/patientInfo/selectExchangeGoods?pageNum=${pageNum}&pageSize=${pageSize}`,
method: 'get' method: 'get'
}) })
} }
//兑换
export function integralGoodsOrder(data) {
return request({
url: `/nurseApplet/patientInfo/integralGoodsOrder`,
method: 'post',
data
})
}

View File

@ -0,0 +1,735 @@
export default{
data(){
return{
system_info:{}, //system info
canvas_width:0, //canvas width px
canvas_height:0, //canvas height px
ctx:null, //canvas object
canvas_id:null, //canvas id
hidden:false,//Whether to hide canvas
scale:1,//canvas scale
r_canvas_scale:1,
if_ctx:true
}
},
methods:{
/**
* save r-canvas.vue object
* @param {Object} that
*/
// saveThis(that){
// rCanvasThis = that
// },
/**
* Draw round rect text
* @param {Object} config
* @param {Number} config.x x坐标
* @param {Number} config.y y坐标
* @param {Number} config.w 宽度
* @param {Number} config.h 高度
* @param {Number} config.radius 圆角弧度
* @param {String} config.fill_color 矩形颜色
*/
fillRoundRect(config) {
return new Promise((resolve,reject)=>{
let x = this.compatibilitySize(parseFloat(config.x)*this.scale)
let y = this.compatibilitySize(parseFloat(config.y)*this.scale)
let w = this.compatibilitySize(parseFloat(config.w)*this.scale)
let h = this.compatibilitySize(parseFloat(config.h)*this.scale)
let radius = config.radius?parseFloat(config.radius)*this.scale:10*this.scale
let fill_color = config.fill_color || "black"
// The diameter of the circle must be less than the width and height of the rectangle
if (2 * radius > w || 2 * radius > h) {
reject("The diameter of the circle must be less than the width and height of the rectangle")
return false;
}
this.ctx.save();
this.ctx.translate(x, y);
//
this.drawRoundRectPath({
w: w,
h: h,
radius: radius
});
this.ctx.fillStyle = fill_color
this.ctx.fill();
this.ctx.restore();
resolve()
})
},
/**
* Draws the sides of a rounded rectangle
* @param {Object} config
* @param {Number} config.w 宽度
* @param {Number} config.h 高度
* @param {Number} config.radius 圆角弧度
*/
drawRoundRectPath(config) {
this.ctx.beginPath(0);
this.ctx.arc(config.w - config.radius, config.h - config.radius, config.radius, 0, Math.PI / 2);
this.ctx.lineTo(config.radius, config.h);
this.ctx.arc(config.radius, config.h - config.radius, config.radius, Math.PI / 2, Math.PI);
this.ctx.lineTo(0, config.radius);
this.ctx.arc(config.radius, config.radius, config.radius, Math.PI, Math.PI * 3 / 2);
this.ctx.lineTo(config.w - config.radius, 0);
this.ctx.arc(config.w - config.radius, config.radius, config.radius, Math.PI * 3 / 2, Math.PI * 2);
this.ctx.lineTo(config.w, config.h - config.radius);
this.ctx.closePath();
},
/**
* Draw special Text,line wrapping is not supported
* @param {Object} config
* @param {String} config.text 文字
* @param {Number} config.x x坐标
* @param {Number} config.y y坐标
* @param {String} config.font_color 文字颜色
* @param {String} config.font_family 文字字体
* @param {Number} config.font_size 文字大小px
*/
drawSpecialText(params){
let general = params.general
let list = params.list
return new Promise(async (resolve,reject)=>{
if(!general){
reject("general cannot be empty:101")
return;
}else if(list && list.length>0){
for(let i in list){
if(i != 0){
let font_size = list[i-1].font_size?parseFloat(list[i-1].font_size):20
this.ctx.setFontSize(font_size)
general.x = parseFloat(general.x) + this.ctx.measureText(list[i-1].text).width
}
list[i].x = general.x
list[i].y = general.y + (list[i].margin_top?parseFloat(list[i].margin_top):0)
await this.drawText(list[i])
}
resolve()
}else{
reject("The length of config arr is less than 0")
return;
}
})
},
/**
* array delete empty
* @param {Object} arr
*/
arrDeleteEmpty(arr){
let newArr = []
for(let i in arr){
if(arr[i]){
newArr.push(arr[i])
}
}
return newArr
},
/**
* Draw Text,support line
* @param {Object} config
* @param {String} config.text 文字
* @param {Number} config.max_width 文字最大宽度大于宽度自动换行
* @param {Number} config.line_height 文字上下行间距
* @param {Number} config.x x坐标
* @param {Number} config.y y坐标
* @param {String} config.font_color 文字颜色
* @param {String} config.font_family 文字字体 默认值Arial
* @param {String} config.text_align 文字对齐方式left/center/right
* @param {Number} config.font_size 文字大小px
* @param {Boolean} config.line_through_height 中划线大小
* @param {Boolean} config.line_through_color 中划线颜色
* @param {String} config.font_style 规定文字样式
* @param {String} config.font_variant 规定字体变体
* @param {String} config.font_weight 规定字体粗细
* @param {String} config.line_through_cap 线末端类型
* @param {String} config.line_clamp 最大行数
* @param {String} config.line_clamp_hint 超过line_clamp后尾部显示的自定义标识 ...
* @param {String} config.is_line_break 是否开启换行符换行
*
*/
drawText(config,configuration = {}){
configuration['line_num'] = configuration.line_num?configuration.line_num:0
configuration['text_width'] = configuration.text_width?configuration.text_width:0
return new Promise(async (resolve,reject)=>{
if(config.text){
let draw_width = 0,draw_height = 0,draw_x = config.x,draw_y = config.y
let font_size = config.font_size?(parseFloat(config.font_size)*this.scale):(20*this.scale)
let font_color = config.font_color || "#000"
let font_family = config.font_family || "Arial"
let line_height = config.line_height || config.font_size || 20
let text_align = config.text_align || "left"
let font_weight = config.font_weight || "normal"
let font_variant = config.font_variant || "normal"
let font_style = config.font_style || "normal"
let line_clamp_hint = config.line_clamp_hint || '...'
let lineBreakJoinText = ""
let max_width = config.max_width?parseFloat(config.max_width)*this.scale:0
// checkout is line break
if(config.is_line_break){
let splitTextArr = config.text.split(/[\n]/g)
if(splitTextArr && splitTextArr.length > 0){
let newSplitTextArr = this.arrDeleteEmpty(splitTextArr)
if(newSplitTextArr && newSplitTextArr.length > 0){
lineBreakJoinText = newSplitTextArr.slice(1).join("\n")
config.text = newSplitTextArr[0]
}else{
reject("Text cannot be empty:103")
return
}
}else{
reject("Text cannot be empty:102")
return
}
}
this.ctx.setFillStyle(font_color) // color
this.ctx.textAlign = text_align;
this.ctx.font = `${font_style} ${font_variant} ${font_weight} ${parseInt(font_size)}px ${font_family}`
if(configuration.text_width >= this.ctx.measureText(config.text).width){
draw_width = configuration.text_width
}else if(max_width > 0){
draw_width = max_width < this.ctx.measureText(config.text).width ? this.resetCompatibilitySize(max_width) : this.resetCompatibilitySize(this.ctx.measureText(config.text).width)
}else{
draw_width = this.ctx.measureText(config.text).width
}
configuration.text_width = draw_width / this.scale
if( max_width && this.compatibilitySize(this.ctx.measureText(config.text).width) > this.compatibilitySize(max_width)){
let current_text = ""
let text_arr = config.text.split("")
for(let i in text_arr){
if( this.compatibilitySize(this.ctx.measureText(current_text+text_arr[i]).width) > this.compatibilitySize(max_width) ){
// Hyphenation that is greater than the drawable width continues to draw
if(config.line_clamp && parseInt(config.line_clamp) == 1){
// Subtracting the current_text tail width from the line_clamp_hint width
let current_text_arr = current_text.split('')
let json_current_text = ''
while(true){
current_text_arr = current_text_arr.slice(1)
json_current_text = current_text_arr.join('')
if(this.compatibilitySize(this.ctx.measureText(json_current_text).width) <= this.compatibilitySize(this.ctx.measureText(line_clamp_hint).width)){
current_text = current_text.replace(json_current_text,'')
break;
}
}
configuration.line_num += 1
this.ctx.setFontSize(parseInt(this.compatibilitySize(font_size))) // font size
this.ctx.fillText(current_text + line_clamp_hint, this.compatibilitySize(parseFloat(config.x)*this.scale), this.compatibilitySize(parseFloat(config.y)*this.scale));
}else{
configuration.line_num += 1
this.ctx.setFontSize(parseInt(this.compatibilitySize(font_size))) // font size
this.ctx.fillText(current_text, this.compatibilitySize(parseFloat(config.x)*this.scale), this.compatibilitySize(parseFloat(config.y)*this.scale));
config.text = text_arr.slice(i).join("")
config.y = config.y + line_height
if(config.line_clamp){
config.line_clamp = parseInt(config.line_clamp) - 1
}
await this.drawText(config,configuration)
}
break;
}else{
current_text = current_text+text_arr[i]
}
}
}else{
if(config.line_through_height){
let x = parseFloat(config.x)*this.scale
let w
let y = parseFloat(config.y)*this.scale - (font_size / 2.6)
if(text_align == "left"){
w = this.ctx.measureText(config.text).width/1.1 + parseFloat(config.x)*this.scale
}else if(text_align == "right"){
w = parseFloat(config.x)*this.scale - this.ctx.measureText(config.text).width/1.1
}else if(text_align == "center"){
x = parseFloat(config.x)*this.scale - this.ctx.measureText(config.text).width / 1.1 / 2
w = parseFloat(config.x)*this.scale + this.ctx.measureText(config.text).width / 1.1 / 2
}
this.drawLineTo({
x:x,
y:y,
w:w,
h:y,
line_width:config.line_through_height,
line_color:config.line_through_color,
line_cap:config.line_through_cap
})
}
configuration.line_num += 1
this.ctx.setFontSize(parseInt(this.compatibilitySize(font_size))) // font size
this.ctx.fillText(config.text, this.compatibilitySize(parseFloat(config.x)*this.scale), this.compatibilitySize(parseFloat(config.y)*this.scale));
if(config.line_clamp){
config.line_clamp = parseInt(config.line_clamp) - 1
}
}
if(lineBreakJoinText){
await this.drawText({...config,text:lineBreakJoinText,y:config.y + line_height},configuration)
}
draw_height = config.font_size * configuration.line_num
draw_width = configuration.text_width
resolve({draw_width,draw_height,draw_x,draw_y})
}else{
reject("Text cannot be empty:101")
}
})
},
/**
* Draw Line
* @param {Object} config
* @param {Object} config.x x坐标
* @param {Object} config.y y坐标
* @param {Object} config.w 线的宽度
* @param {Object} config.h 线的高度
* @param {Object} config.line_width 线的宽度
* @param {Object} config.line_color 线条颜色
*/
drawLineTo(config){
let x = this.compatibilitySize(config.x)
let y = this.compatibilitySize(config.y)
let w = this.compatibilitySize(config.w)
let h = this.compatibilitySize(config.h)
let line_width = config.line_width?parseFloat(config.line_width)*this.scale:1*this.scale
let line_color = config.line_color || "black"
let line_cap = config.line_cap || "butt"
this.ctx.beginPath()
this.ctx.lineCap = line_cap
this.ctx.lineWidth = line_width
this.ctx.strokeStyle = line_color
this.ctx.moveTo(x,y)
this.ctx.lineTo(w,h)
this.ctx.stroke()
},
/**
* Compatibility px
* @param {Object} size
*/
compatibilitySize(size) {
let canvasSize = (parseFloat(size) / 750) * this.system_info.windowWidth
canvasSize = parseFloat(canvasSize * 2)
return canvasSize
},
/**
* Restore compatibility px
* @param {Object} size
*/
resetCompatibilitySize(size) {
let canvasSize = (parseFloat(size/2)/this.system_info.windowWidth) * 750
return canvasSize
},
/**
* Init canvas
*/
init(config){
return new Promise(async (resolve,reject)=>{
if(!config.canvas_id){
reject("Canvas ID cannot be empty, please refer to the usage example")
return;
}
this.hidden = config.hidden
this.canvas_id = config.canvas_id
let system_info = await uni.getSystemInfoSync()
this.system_info = system_info
this.scale = config.scale&&parseFloat(config.scale)>0?parseInt(config.scale):1
this.canvas_width = (config.canvas_width ? this.compatibilitySize(config.canvas_width) : system_info.windowWidth) * this.scale
this.canvas_height = (config.canvas_height ? this.compatibilitySize(config.canvas_height) : system_info.windowHeight) * this.scale,
this.r_canvas_scale = 1/this.scale
this.ctx = uni.createCanvasContext(this.canvas_id,this)
this.setCanvasConfig({
global_alpha:config.global_alpha?parseFloat(config.global_alpha):1,
backgroundColor:config.background_color?config.background_color:"#fff"
})
resolve()
})
},
/**
* clear canvas all path
*/
clearCanvas(){
return new Promise(async (resolve,reject)=>{
if(!this.ctx){
reject("canvas is not initialized:101")
return
}else{
this.ctx.clearRect(0,0,parseFloat(this.canvas_width)*this.scale,parseFloat(this.canvas_height)*this.scale)
await this.draw()
resolve()
}
})
},
/**
* Set canvas config
* @param {Object} config
*/
setCanvasConfig(config){
this.ctx.globalAlpha = config.global_alpha
this.ctx.fillStyle = config.backgroundColor
this.ctx.fillRect(0, 0, parseFloat(this.canvas_width)*this.scale, parseFloat(this.canvas_height)*this.scale)
},
/**
* set canvas width
* @param {Object} width
*/
setCanvasWidth(width){
if(!width){
// uni.showToast({
// title:'setCanvasWidthwidth error',
// icon:'none'
// })
}
this.canvas_width = this.compatibilitySize(parseFloat(width)) * this.scale
this.ctx.width = this.canvas_width
},
/**
* set canvas height
* @param {Object} height
*/
setCanvasHeight(height){
if(!height){
// uni.showToast({
// title:'setCanvasWidthheight error',
// icon:'none'
// })
}
this.canvas_height = this.compatibilitySize(parseFloat(height)) * this.scale
this.ctx.height = this.canvas_height
},
/**
* Draw to filepath
*/
draw(callback){
return new Promise((resolve,reject)=>{
let stop = setTimeout(()=>{
this.ctx.draw(false,setTimeout(()=>{
uni.canvasToTempFilePath({
canvasId: this.canvas_id,
quality: 1,
success: (res)=>{
console.log('res',res)
resolve(res)
callback && callback(res)
},
fail:(err)=>{
reject(JSON.stringify(err)|| "Failed to generate poster:101")
}
},this)
},300))
clearTimeout(stop)
},300)
})
},
/**
* draw rect
* @param {Number} config.x x坐标
* @param {Number} config.y y坐标
* @param {Number} config.w 图形宽度(px)
* @param {Number} config.h 图形高度(px)
* @param {Number} config.color 图形颜色
* @param {Number} config.is_radius 是否开启圆图1.1.6及以下版本废弃请使用border_radius
* @param {Number} config.border_width 边框大小
* @param {Number} config.border_color 边框颜色
*
*/
drawRect(config){
return new Promise(async (resolve,reject)=>{
if(!config.border_width || config.border_width <=0){
config.border_width = 0
}else{
config.border_width = parseFloat(config.border_width)
}
if(parseFloat(config.border_width) > 0){
let sub_config = JSON.parse(JSON.stringify(config))
sub_config.border_width = 0
sub_config.w = config.w + config.border_width
sub_config.h = config.h + config.border_width
sub_config.color = config.border_color || 'black'
if(sub_config.border_radius){
sub_config.border_radius = parseFloat(sub_config.border_radius) + parseFloat(config.border_width) / 2
}
await this.drawRect(sub_config)
}
let color = config.color || 'white'
config.x = (parseFloat(config.x) + config.border_width / 2)
config.y = (parseFloat(config.y) + config.border_width / 2)
config['color'] = color
this.ctx.fillStyle = color;
if(config.is_radius || config.border_radius){
this.setNativeBorderRadius(config)
this.ctx.fill()
}else{
console.log('config.border_width',config.border_width)
this.ctx.fillRect(this.compatibilitySize(config.x*this.scale),this.compatibilitySize(config.y*this.scale),this.compatibilitySize(parseFloat(config.w)*this.scale),this.compatibilitySize(parseFloat(config.h)*this.scale))
}
resolve()
})
},
/**
* Draw image
* @param {Object} config
* @param {String} config.url 图片链接
* @param {Number} config.x x坐标
* @param {Number} config.y y坐标
* @param {Number} config.w 图片宽度(px)
* @param {Number} config.h 图片高度(px)
* @param {Number} config.border_width 边大小
* @param {Number} config.border_color 边颜色
* @param {Number} config.is_radius 是否开启圆图1.1.6及以下版本废弃请使用border_radius
* @param {Number} config.border_radius 圆角弧度
*/
drawImage(config){
return new Promise(async (resolve,reject)=>{
if(config.url){
let type = 0 // 1、network image 2、native image 3、base64 image
let image_url
let reg = /^https?/ig;
if(reg.test(config.url)){
type = 1
}else{
if((config.url.indexOf("data:image/png;base64") != -1) || config.url.indexOf("data:image/jpeg;base64") != -1 || config.url.indexOf("data:image/gif;base64") != -1){
type = 3
}else{
type = 2
}
}
if(type == 1){
// network image
await this.downLoadNetworkFile(config.url).then(res=>{ // two function
image_url = res
}).catch(err=>{
reject(err)
return;
})
}else if(type == 2){
// native image
const imageInfoResult = await uni.getImageInfo({
src: config.url
});
try{
if(imageInfoResult.length <= 1){
reject(imageInfoResult[0].errMsg + ':404')
return
}
}catch(e){
reject(e+':500')
return
}
let base64 = await this.urlToBase64({url:imageInfoResult[1].path})
// #ifdef MP-WEIXIN
await this.base64ToNative({url:base64}).then(res=>{
image_url = res
}).catch(err=>{
reject(JSON.stringify(err)+":501")
return;
})
// #endif
// #ifndef MP-WEIXIN
image_url = base64
// #endif
}else if(type == 3){
// #ifdef MP-WEIXIN
await this.base64ToNative({url:config.url}).then(res=>{
image_url = res
}).catch(err=>{
reject(JSON.stringify(err)+":500")
return;
})
// #endif
// #ifndef MP-WEIXIN
image_url = config.url
// #endif
}else{
reject("Other Type Errors:101")
return
}
if(config.border_width){
let border_radius = 0
if(config.border_radius){
let multiple = config.w / config.border_radius
border_radius = (parseFloat(config.w) + parseFloat(config.border_width)) / multiple
}
// drawRect
await this.drawRect({
x:parseFloat(config.x) - parseFloat(config.border_width)/2,
y:parseFloat(config.y) - parseFloat(config.border_width)/2,
w:parseFloat(config.w) + parseFloat(config.border_width),
h:parseFloat(config.h) + parseFloat(config.border_width),
color:config.border_color,
border_radius:border_radius,
border_width:config.border_width,
is_radius:config.is_radius
})
}
if(config.border_radius){
config.color = config.color?config.color:'rgba(0,0,0,0)'
// 圆角有白边,+0.5的误差
config.w = config.w + 0.3
config.h = config.h + 0.3
this.setNativeBorderRadius(config)
}else if(config.is_radius){
//已废弃 is_radius
this.ctx.setStrokeStyle("rgba(0,0,0,0)")
this.ctx.save()
this.ctx.beginPath()
this.ctx.arc(this.compatibilitySize(parseFloat(config.x)*this.scale+parseFloat(config.w)*this.scale/2), this.compatibilitySize(parseFloat(config.y)*this.scale+parseFloat(config.h)*this.scale/2), this.compatibilitySize(parseFloat(config.w)*this.scale/2), 0, 2 * Math.PI, false)
this.ctx.stroke();
this.ctx.clip()
}
await this.ctx.drawImage(image_url,this.compatibilitySize(parseFloat(config.x)*this.scale),this.compatibilitySize(parseFloat(config.y)*this.scale),this.compatibilitySize(parseFloat(config.w)*this.scale),this.compatibilitySize(parseFloat(config.h)*this.scale))
this.ctx.restore() //Restore previously saved drawing context
resolve()
}else{
let err_msg = "Links cannot be empty:101"
reject(err_msg)
}
})
},
/**
* base64 to native available path
* @param {Object} config
*/
base64ToNative(config){
return new Promise((resolve,reject)=>{
let fileName = new Date().getTime()
var filePath = `${wx.env.USER_DATA_PATH}/${fileName}_rCanvas.png`
wx.getFileSystemManager().writeFile({
filePath: filePath,
data: config.url.replace(/^data:\S+\/\S+;base64,/, ''),
encoding: 'base64',
success: function() {
resolve(filePath)
},
fail: function(error) {
reject(error)
}
})
})
},
/**
* native url to base64
* @param {Object} config
*/
urlToBase64(config){
return new Promise(async (resolve,reject)=>{
if (typeof window != 'undefined') {
await this.downLoadNetworkFile(config.url).then(res=>{ // two function
resolve(res)
}).catch(err=>{
reject(err)
})
}else if (typeof plus != 'undefined') {
plus.io.resolveLocalFileSystemURL(config.url,(obj)=>{
obj.file((file)=>{
let fileReader = new plus.io.FileReader()
fileReader.onload = (res)=>{
resolve(res.target.result)
}
fileReader.onerror = (err)=>{
reject(err)
}
fileReader.readAsDataURL(file)
}, (err)=>{
reject(err)
})
},(err)=>{
reject(err)
})
}else if(typeof wx != 'undefined'){
wx.getFileSystemManager().readFile({
filePath: config.url,
encoding: 'base64',
success: function(res) {
resolve('data:image/png;base64,' + res.data)
},
fail: function(error) {
reject(error)
}
})
}
})
},
setNativeBorderRadius(config){
let border_radius = config.border_radius?(parseFloat(config.border_radius)*this.scale):(20*this.scale)
if ((parseFloat(config.w)*this.scale) < 2 * border_radius) border_radius = (parseFloat(config.w)*this.scale) / 2;
if ((parseFloat(config.h)*this.scale) < 2 * border_radius) border_radius = (parseFloat(config.h)*this.scale) / 2;
this.ctx.beginPath();
this.ctx.moveTo(this.compatibilitySize((parseFloat(config.x)*this.scale) + border_radius), this.compatibilitySize((parseFloat(config.y)*this.scale)));
this.ctx.arcTo(this.compatibilitySize((parseFloat(config.x)*this.scale) + (parseFloat(config.w)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale)), this.compatibilitySize((parseFloat(config.x)*this.scale) + (parseFloat(config.w)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale) + (parseFloat(config.h)*this.scale)), this.compatibilitySize(border_radius));
this.ctx.arcTo(this.compatibilitySize((parseFloat(config.x)*this.scale) + (parseFloat(config.w)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale) + (parseFloat(config.h)*this.scale)), this.compatibilitySize((parseFloat(config.x)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale) + (parseFloat(config.h)*this.scale)), this.compatibilitySize(border_radius));
this.ctx.arcTo((this.compatibilitySize(parseFloat(config.x)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale) + (parseFloat(config.h)*this.scale)), this.compatibilitySize((parseFloat(config.x)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale)), this.compatibilitySize(border_radius));
this.ctx.arcTo(this.compatibilitySize((parseFloat(config.x)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale)), this.compatibilitySize((parseFloat(config.x)*this.scale) + (parseFloat(config.w)*this.scale)), this.compatibilitySize((parseFloat(config.y)*this.scale)), this.compatibilitySize(border_radius));
this.ctx.closePath();
this.ctx.strokeStyle = config.color || config.border_color || 'rgba(0,0,0,0)'; // 设置绘制边框的颜色
this.ctx.stroke();
this.ctx.save()
this.ctx.clip();
},
/**
* Download network file
* @param {Object} url : download url
*/
downLoadNetworkFile(url){
return new Promise((resolve,reject)=>{
uni.downloadFile({
url,
success:(res)=>{
if(res.statusCode == 200){
resolve(res.tempFilePath)
}else{
reject("Download Image Fail:102")
}
},
fail:(err)=>{
reject("Download Image Fail:101")
}
})
})
},
/**
* Save image to natice
* @param {Object} filePath native imageUrl
*/
saveImage(filePath){
return new Promise((resolve,reject)=>{
if(!filePath){
reject("FilePath cannot be null:101")
return;
}
// #ifdef H5
var createA = document.createElement("a");
createA.download = filePath;
createA.href = filePath;
document.body.appendChild(createA);
createA.click();
createA.remove();
resolve()
// #endif
// #ifndef H5
uni.saveImageToPhotosAlbum({
filePath: filePath,
success:(res)=>{
resolve(res)
},
fail:(err)=>{
reject(err)
}
})
// #endif
})
}
}
}

View File

@ -0,0 +1,26 @@
<template>
<view>
<view class="r-canvas-component" :style="{width:canvas_width/scale+'px',height:canvas_height/scale+'px'}" :class="{'hidden':hidden}">
<canvas class="r-canvas" v-if="canvas_id" :canvas-id="canvas_id" :id="canvas_id" :style="{width:canvas_width+'px',height:canvas_height+'px','transform': `scale(${r_canvas_scale})`}"></canvas>
</view>
</view>
</template>
<script>
import rCanvasJS from "./r-canvas.js"
export default {
mixins:[rCanvasJS]
}
</script>
<style>
.r-canvas{
transform-origin: 0 0;
}
.r-canvas-component{
overflow: hidden;
}
.r-canvas-component.hidden{
position: fixed;
top:-5000upx;
}
</style>

View File

@ -1,5 +1,16 @@
{ {
"dependencies": { "dependencies": {
"uview-ui": "^1.8.4" "uview-ui": "^1.8.4"
} },
"id": "r-canvas",
"name": "海报生成随心所欲绘制样式原生canvas方法的二次封装自定义函数持续更新",
"version": "1.3.1",
"description": "图片不失帧保留原有画质canvas方法扩展暴露原生实例可自行扩展最好用的canvas插件",
"keywords": [
"canvas",
"画布生成图片",
"绘制图片",
"商品海报",
"朋友圈海报"
]
} }

View File

@ -4,19 +4,19 @@
}, },
"pages": [ //pageshttps://uniapp.dcloud.io/collocation/pages "pages": [ //pageshttps://uniapp.dcloud.io/collocation/pages
{ {
"path": "pages/integral/integral",
"style": {
"navigationBarTitleText": "积分",
"enablePullDownRefresh": false,
"navigationBarBackgroundColor": "#ffffff"
}
},{
"path": "pages/startup/startup", "path": "pages/startup/startup",
"style": { "style": {
"navigationBarTitleText": "", "navigationBarTitleText": "",
"navigationStyle": "custom" "navigationStyle": "custom"
} }
},{ },{
"path": "pages/integral/integral",
"style": {
"navigationBarTitleText": "积分",
"enablePullDownRefresh": false,
"navigationBarBackgroundColor": "#ffffff"
}
}, {
"path": "pages/information/information", "path": "pages/information/information",
"style": { "style": {
"navigationBarTitleText": "完善个人信息", "navigationBarTitleText": "完善个人信息",

View File

@ -25,15 +25,25 @@
<view class="model"> <view class="model">
<view class="top"> <view class="top">
<span>{{item.goodsName}}</span> <span>{{item.goodsName}}</span>
<span>{{item.goodsPrice}}</span> <span v-if="item.goodsPrice">{{item.goodsPrice}}</span>
</view> </view>
<view class="bottom"> <view class="bottom">
<span class="box">型号{{item.goodsAttributeName}}</span> <span class="box">型号{{item.goodsAttributeName}}</span>
<span class="box">×{{item.goodsCount}}</span> <span class="box">×{{item.goodsCount}}</span>
</view> </view>
<view class="refund"> <view class="refund">
实付款 <span v-if="item.orderType=='DIRECT_BUY'">
<text class="price">{{item.totalPrice}}</text> 实付款
</span>
<span v-if="item.orderType=='INTEGRAL_EXCHANGE'">
实付
</span>
<text class="price" v-if="item.orderType=='DIRECT_BUY'">{{item.totalPrice}}</text>
<text class="price"
v-if="item.orderType=='INTEGRAL_EXCHANGE'">{{item.integralExchangeSill}}</text>
<span v-if="item.orderType=='INTEGRAL_EXCHANGE'" style='padding-left: 10rpx;'>
积分
</span>
</view> </view>
</view> </view>
</view> </view>
@ -74,7 +84,7 @@
<image :src="baseurl+img" mode=""></image> <image :src="baseurl+img" mode=""></image>
<view class="blackground">共1件</view> <view class="blackground">共1件</view>
</view> </view>
<view class="word">为了保证的售后权益请收到商品确认无误后再确认收货</view> <view class="word">为了保证的售后权益请收到商品确认无误后再确认收货</view>
</view> </view>
<view class="submits" @tap='Receipts'>确定</view> <view class="submits" @tap='Receipts'>确定</view>
</u-popup> </u-popup>
@ -252,20 +262,16 @@
this.pageNum = 1; this.pageNum = 1;
this.baseurl = baseurl; this.baseurl = baseurl;
let that = this let that = this
try { const value = uni.getStorageSync('openid');
const value = uni.getStorageSync('openid'); if (value) {} else {
if (value) {} else { uni.navigateTo({
uni.navigateTo({ url: '/pages/login/login'
url: '/pages/login/login' })
}) }
} const value3 = uni.getStorageSync('Refresh');
} catch (e) {} if (value3) {
try { that.goodsOrderinfo();
const value3 = uni.getStorageSync('Refresh'); }
if (value3) {
that.goodsOrderinfo();
}
} catch (e) {}
}, },
onLoad(options) { // onLoad(options) { //
let that = this let that = this

View File

@ -148,7 +148,7 @@
.item { .item {
width: 100%; width: 100%;
height: 200rpx; height: 250rpx;
position: relative; position: relative;
border-bottom: 2rpx solid #CDC9C9; border-bottom: 2rpx solid #CDC9C9;
@ -157,8 +157,8 @@
right: 0; right: 0;
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
width: 253rpx; width: 200rpx;
height: 164rpx; height: 200rpx;
border-radius: 10rpx; border-radius: 10rpx;
} }
@ -176,6 +176,13 @@
left: 0; left: 0;
width: 60%; width: 60%;
font-size: 30rpx; font-size: 30rpx;
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 5; //
line-clamp: 5;
-webkit-box-orient: vertical;
} }
} }
} }

View File

@ -34,15 +34,21 @@
<image src="../../static/jifen.png" mode=""></image> <image src="../../static/jifen.png" mode=""></image>
<view class="text"> <view class="text">
积分 积分
<span style='padding:0 5rpx' v-if="appPersonallist.integral>=0"> {{appPersonallist.integral}}</span> <span style='padding:0 5rpx' v-if="appPersonallist.integral&&appPersonallist.integral>=0">
{{appPersonallist.integral}}</span>
<span style='padding:0 5rpx' v-else>
0</span>
</view> </view>
</view> </view>
<view class="item" @tap="gocoupon"> <view class="item" @tap="gocoupon">
<image src="../../static/yhj.png" mode=""></image> <image src="../../static/yhj.png" mode=""></image>
<view class="text"> <view class="text">
优惠券 优惠券
<span style='padding:0 5rpx' v-if="appPersonallist.patientCouponCount>=0"> <span style='padding:0 5rpx'
{{appPersonallist.patientCouponCount}}</span> v-if="appPersonallist.patientCouponCount&&appPersonallist.patientCouponCount>=0">
{{appPersonallist.patientCouponCount}}</span>
<span style='padding:0 5rpx' v-else>
0</span>
</view> </view>
</view> </view>
</view> </view>

View File

@ -372,9 +372,13 @@
left: 0; left: 0;
width: 65%; width: 65%;
font-size: 30rpx; font-size: 30rpx;
// overflow: hidden; text-overflow: -o-ellipsis-lastline;
// text-overflow: ellipsis; overflow: hidden;
// white-space: nowrap; text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 5; //
line-clamp: 5;
-webkit-box-orient: vertical;
} }
} }
} }

View File

@ -31,19 +31,19 @@
{{item.goodsName}} {{item.goodsName}}
</view> </view>
<view class="text"> <view class="text">
{{item.attributeDetailsName}} {{item.integralExchangeCount}}{{item.goodsUnit}}
</view> </view>
<view class="jifen"> <view class="jifen">
需使用 需使用
<span style='padding: 0 5rpx;'> {{item.integralExchangeSill}}</span> <span style='padding: 0 5rpx;'> {{item.integralExchangeSill}}</span>
积分兑换 积分兑换
</view> </view>
<view class="btn"> <view class="btn" @tap='buyshowtrue(item)'>
立即兑换 立即兑换
</view> </view>
</view> </view>
</view> </view>
<u-mask :show="gainshow" @tap="gainshow = false"> <u-mask :show="gainshow" @click="gainshow = false">
<view class="mask" @click.stop=""> <view class="mask" @click.stop="">
<view class="title"> <view class="title">
获取方式 获取方式
@ -77,18 +77,82 @@
<view class="text"> <view class="text">
<span style='padding: 0 5rpx;'> {{list.inviteFriends}}</span>积分 <span style='padding: 0 5rpx;'> {{list.inviteFriends}}</span>积分
</view> </view>
<view class="btn" style="color: #F44B2F;" @tap="yaoqingshowtrue"> <view class="btn" style="color: #F44B2F;" @tap='yaoqingshowtrue'>
去完成 去完成
</view> </view>
</view> </view>
</view> </view>
</view> </view>
</u-mask> </u-mask>
<u-mask :show="yaoqingshow" @tap="yaoqingshowfalse"> <u-mask :show="buyshow" @click="buyshow = false">
<view class="masks" @click.stop=""> <view class="PurchasePage" @click.stop=''>
<r-canvas ref="rCanvas"></r-canvas> <image class="close" src="../../static/gb.png" mode="" @tap='buyshow=false'></image>
</image>
<view class="topcontent" style="width: 96%;">
<view class="image">
<image :src="goodsitem.goodsPictureUrl" mode=""></image>
</view>
<view class="title" v-if="goodsitem.goodsName">
{{goodsitem.goodsName}}
</view>
<view class="title" v-else>
暂无
</view>
<view class="prices">
<span class="price">
{{goodsitem.integralExchangeSill}}积分
</span>
</view>
<view class="goodsStock">
库存数量:{{goodsitem.goodsStock}}
</view>
</view>
<view class="bodys" @tap='upaddress()'>
<view class="addressinfo">
<image src="../../static/locatinsmall.png" mode=""></image>
<view class="namephone" v-if='userid'>
{{updata.receiver}},{{updata.phone}}
</view>
<view class="address" v-if='userid'>
{{updata.receiveAddress}}
</view>
<view class="namephone" v-else>
前往完善个人信息
</view>
<view class="picture2">
<u-icon name="arrow-right" color="black" size="28"></u-icon>
</view>
</view>
</view>
<view class="centercontent topcontent">
<view class="header">
商品规格
</view>
<view style="display: flex;justify-content: flex-start;flex-wrap: wrap;">
<view class="Productmodel productmodel">
<image :src="baseurl+goodsitem.attributePitureUrl" mode=""></image>
<view class="">
{{goodsitem.integralExchangeCount}}{{goodsitem.goodsUnit}}
</view>
</view>
</view>
</view>
<view class="buy" @tap="upbuy">
立即兑换
</view>
</view> </view>
</u-mask> </u-mask>
<u-popup v-model="yaoqingshow" mode="center" :closeable='true' :close='yaoqingshowfalse'>
<view class="yaoqing">
<r-canvas ref="rCanvas" v-if="yaoqingshow"></r-canvas>
</view>
<view class="yaoqbtn" @tap='draw'>
保存到相册
</view>
<view class="yaoqbtn2" @tap='fenx'>
分享给好友
</view>
</u-popup>
<u-toast ref="uToast" /> <u-toast ref="uToast" />
</view> </view>
</template> </template>
@ -96,46 +160,309 @@
import { import {
signIn, signIn,
selectPatientSignIn, selectPatientSignIn,
selectExchangeGoods selectExchangeGoods,
integralGoodsOrder
} from '@/api/integral/index.js' } from '@/api/integral/index.js'
import { import {
inviteFriends inviteFriends
} from '@/api/Personal/Personal.js'; } from '@/api/Personal/Personal.js';
import {
goodPatientInfo
} from '@/api/modifyAddress/modifyAddress.js';
import baseurl from '../../api/baseurl'; import baseurl from '../../api/baseurl';
import rCanvas from "@/components/r-canvas/r-canvas.vue"
export default { export default {
components: {
rCanvas
},
data() { data() {
return { return {
integral: 0, baseurl: '',
gainshow: false,
yaoqingshow: false,
patientId: null, patientId: null,
integral: 0,
gainshow: false, //
buyshow: false, //
yaoqingshow: false,
yaoqingimg: null,
list: null, list: null,
inviteimg: null, inviteimg: null, //
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
goodstotal: 0, goodstotal: 0,
goodslist: null, goodslist: null,
goodsitem: null,
userid: null,
updata: {
"orderChannel": 'WECHAT_APPLET',
"originalTotalPrice": null,
"integralExchangeSill": null,
"integralExchangeCount": null,
"orderType": "INTEGRAL_EXCHANGE",
"buySource": "SHOPPING_MALL",
"integralDeductionCount": null,
"attributeDetailsId": null,
"discountPrice": null,
"giveIntegral": null,
"goodsAttributeContent": null,
"goodsAttributeDetailsId": null,
"goodsAttributeId": null,
"goodsAttributeName": null,
"goodsCount": null,
"goodsName": null,
"goodsPrice": null,
"goodsStock": null,
"nurseStationId": null,
"patientId": null,
"phone": "18963146613",
"receiveAddress": null,
"receiver": null,
}
}; };
},
onReady() {
}, },
onLoad(options) { onLoad(options) {
this.baseurl = baseurl
this.integral = options.integral this.integral = options.integral
var that = this var that = this
this.selectExchangeGoodsinfo(); this.selectExchangeGoodsinfo();
const value = uni.getStorageSync('patientId'); const value = uni.getStorageSync('patientId');
if (value) { if (value) {
that.patientId = value that.patientId = value
that.updata.patientId = value
that.selectPatientSignInifo(); that.selectPatientSignInifo();
inviteFriends(value).then(res => { that.goodsList();
that.inviteimg = res.msg
})
} }
}, },
onShow() {
var that = this
this.baseurl = baseurl
const value = uni.getStorageSync('patientId');
if (value) {
that.updata.patientId = value
goodPatientInfo(value).then(res => {
if (res.code == 200) {
var user = res.data.filter(e => e.id == that.userid)
if (user.length >= 1) {
that.updata.receiver = user[0].receiveName
that.updata.receiveAddress = user[0].areaName + user[0].receiveAddress
that.updata.phone = user[0].receivePhone
that.userid = user[0].id
} else {
that.updata.receiver = res.data[0].receiveName
that.updata.receiveAddress = res.data[0].areaName + res.data[0].receiveAddress
that.updata.phone = res.data[0].receivePhone
that.userid = res.data[0].id
}
}
})
} else {}
let useritem = null
uni.$on('updata', function(data) {
if (data.useritem) {
useritem = JSON.parse(data.useritem)
that.updata.receiver = useritem.receiveName
that.updata.phone = useritem.receivePhone
that.updata.receiveAddress = useritem.areaName + useritem.receiveAddress
that.userid = useritem.id
}
})
},
methods: { methods: {
yaoqingshowfalse() {}, yaoqingshowtrue() {
this.yaoqingshow = true
this.$nextTick(async () => {
await inviteFriends(this.patientId).then(res => {
this.inviteimg = res.msg
})
uni.showLoading({
title: '加载中'
});
//
await this.$refs.rCanvas.init({
canvas_id: "rCanvas"
})
//
await this.$refs.rCanvas.drawImage({
url: "/static/yaoqinghaoyou.png",
x: 0,
y: 0,
w: 330,
h: 600
}).catch(err_msg => {
uni.showToast({
title: err_msg,
icon: "none"
})
})
await this.$refs.rCanvas.drawImage({
url: baseurl + this.inviteimg,
x: 100,
y: 370,
w: 130,
h: 130
}).catch(err_msg => {
uni.showToast({
title: err_msg,
icon: "none"
})
})
//
await this.$refs.rCanvas.drawText({
text: "智慧康养泉城,医护关怀到家",
x: 165,
y: 330,
font_color: "#444444",
font_size: 12,
font_weight: 600,
text_align: 'center'
}).catch(err_msg => {
uni.showToast({
title: err_msg,
icon: "none"
})
})
await this.$refs.rCanvas.drawText({
text: "超多福利,快来体验吧!",
x: 165,
y: 350,
font_color: "#444444",
font_size: 12,
font_weight: 600,
text_align: 'center'
}).catch(err_msg => {
uni.showToast({
title: err_msg,
icon: "none"
})
})
await this.$refs.rCanvas.drawText({
text: "泉医到家小程序",
x: 165,
y: 530,
font_color: "#444444",
font_size: 10,
text_align: 'center'
}).catch(err_msg => {
uni.showToast({
title: err_msg,
icon: "none"
})
})
await this.$refs.rCanvas.drawText({
text: "(长按识别二维码开启健康之旅)",
x: 165,
y: 543,
font_color: "#444444",
font_size: 7,
text_align: 'center'
}).catch(err_msg => {
uni.showToast({
title: err_msg,
icon: "none"
})
})
//
await this.$refs.rCanvas.draw((res) => {
this.yaoqingimg = res.tempFilePath
uni.hideLoading();
//res.tempFilePathbase64
//
// this.$refs.rCanvas.saveImage(res.tempFilePath)
})
})
},
//
draw() {
//
this.$refs.rCanvas.saveImage(this.yaoqingimg).then(res => {
uni.showToast({
title: '保存成功',
duration: 2000
});
}).catch(err => {
uni.showToast({
icon: 'error',
title: '保存失败',
duration: 2000
});
})
},
//
fenx() {
wx.showShareImageMenu({
path: this.yaoqingimg,
})
},
yaoqingshowfalse() {
this.yapqingshow = false;
this.$nextTick(async () => {
await this.$refs.rCanvas.clearCanvas((res) => {
console.log(res)
})
await this.$refs.rCanvas.setCanvasWidth(0)
await this.$refs.rCanvas.setCanvasHeight(0)
})
},
//
upbuy() {
integralGoodsOrder(this.updata).then(res => {
if (res.code == 200) {
this.$refs.uToast.show({
title: '兑换商品成功',
type: 'success'
})
this.buyshow = false
} else {
this.$refs.uToast.show({
title: '兑换商品失败',
type: 'error'
})
}
})
},
//
upaddress() {
if (this.updata.receiver) {
uni.navigateTo({
url: `/pages/modifyAddress/modifyAddress?updata=${JSON.stringify(this.updata)}`
})
} else {
const value = uni.getStorageSync('openid');
const value2 = uni.getStorageSync('patientId');
if (value && value2) {
uni.navigateTo({
url: '/pages/information/information'
})
} else {
this.$refs.uToast.show({
title: '未登录,请先登录',
type: 'error'
})
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(e => {
uni.navigateTo({
url: '/pages/login/login'
})
}, 1500)
}
}
},
///
buyshowtrue(item) {
this.buyshow = true
this.goodsitem = item
this.updata.goodsAttributeName = this.goodsitem.attributeDetailsName
this.updata.goodsAttributeId = this.goodsitem.goodsAttributeId
this.updata.goodsAttributeDetailsId = this.goodsitem.attributeDetailsId
this.updata.integralExchangeSill = this.goodsitem.integralExchangeSill
this.updata.integralExchangeCount = this.goodsitem.integralExchangeCount
this.updata.originalTotalPrice = 0
this.updata.goodsStock = this.goodsitem.goodsStock
this.updata.goodsName = this.goodsitem.goodsName
this.updata.goodsPrice = this.goodsitem.goodsPrice
this.updata.goodsCount = 1
},
// //
selectExchangeGoodsinfo() { selectExchangeGoodsinfo() {
selectExchangeGoods(this.pageNum, this.pageSize).then(res => { selectExchangeGoods(this.pageNum, this.pageSize).then(res => {
@ -165,6 +492,23 @@
} }
}) })
}, },
//
goodsList() {
goodPatientInfo(this.patientId).then(res => {
var list = res.data.filter(e => e.defaultAddressFlag == 1)
if (list.length >= 1) {
this.updata.receiver = list[0].receiveName
this.updata.receiveAddress = list[0].areaName + list[0].receiveAddress
this.updata.phone = list[0].receivePhone
this.userid = list[0].id
} else {
this.updata.receiver = res.data[0].receiveName
this.updata.receiveAddress = res.data[0].areaName + res.data[0].receiveAddress
this.updata.phone = res.data[0].receivePhone
this.userid = res.data[0].id
}
})
},
}, },
onReachBottom() { // onReachBottom() { //
if (this.goodslist.length >= this.goodstotal) {} else { if (this.goodslist.length >= this.goodstotal) {} else {
@ -189,21 +533,246 @@
<style lang="scss"> <style lang="scss">
.app { .app {
.masks { ::v-deep .r-canvas {
margin: 50rpx auto 0; width: 660rpx !important;
height: 1100rpx; height: 1100rpx !important;
width: 620rpx; margin: 0 auto;
}
::v-deep .r-canvas { ::v-deep .r-canvas-component {
height: 1100rpx !important; width: 660rpx !important;
width: 620rpx !important; height: 1100rpx !important;
margin: 0 auto; margin: 0 auto;
}
::v-deep .u-mode-center-box {
background: none !important;
}
.yaoqbtn {
color: #fff;
position: absolute;
bottom: 0;
text-align: center;
line-height: 71rpx;
left: 0;
width: 251rpx;
height: 71rpx;
background: linear-gradient(90deg, #85C8AE 0%, #03AD6B 59%);
border-radius: 36rpx;
}
.yaoqbtn2 {
color: #fff;
position: absolute;
text-align: center;
line-height: 71rpx;
bottom: 0;
right: 0;
width: 251rpx;
height: 71rpx;
background: linear-gradient(90deg, #64B0F9 0%, #436BF6 59%);
border-radius: 36rpx;
}
.yaoqing {
height: 1200rpx;
}
.PurchasePage {
position: fixed;
bottom: 0;
height: 930rpx;
width: 100%;
background: #FFFFFF;
border-radius: 30rpx 30rpx 0px 0px;
font-size: 36rpx;
padding-bottom: 20rpx;
z-index: 10;
.bodys {
background-color: #FFFFFF;
width: 96%;
margin: 10rpx auto 0;
border-radius: 20rpx;
padding: 15rpx 0 20rpx;
position: relative;
.addressinfo {
font-size: 32rpx;
line-height: 65rpx;
margin-left: 90rpx;
image {
width: 40rpx;
height: 50rpx;
position: absolute;
top: 50%;
left: 20rpx;
transform: translateY(-50%);
}
.address {
padding-top: 10rpx;
width: 92%;
font-size: 30rpx;
word-break: break-all;
line-height: 45rpx;
}
.namephone {
width: 70%;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.picture2 {
position: absolute;
top: 50%;
right: 20rpx;
transform: translateY(-50%);
image {
width: 18rpx;
height: 18rpx;
color: #FFFFFF;
margin-left: 20rpx;
}
}
}
} }
::v-deep .r-canvas-component { .close {
height: 1100rpx !important; width: 31rpx;
width: 620rpx !important; height: 31rpx;
position: absolute;
top: 2%;
right: 2%;
z-index: 999;
}
.topcontent {
width: 96%;
margin: 0 auto; margin: 0 auto;
padding-bottom: 15rpx;
position: relative;
.goodsStock {
font-size: 24rpx;
position: absolute;
top: 75%;
right: 10rpx;
}
.prices {
position: absolute;
top: 70%;
left: 35%;
.price {
color: #D43953;
}
}
.title {
font-size: 36rpx;
position: absolute;
top: 3%;
left: 35%;
font-weight: 600;
width: 58%;
// height: 85rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
word-break: break-all;
}
.image {
width: 200rpx;
height: 200rpx;
margin: 15rpx 0 0 0;
image {
width: 201rpx;
height: 201rpx;
margin: 7rpx 0 0 7rpx;
}
}
}
.buy {
width: 60%;
height: 71rpx;
background: #4C7BC9;
color: #FFFFFF;
text-align: center;
line-height: 71rpx;
border-radius: 26rpx;
position: absolute;
bottom: 30rpx;
left: 20%;
}
.centercontent {
font-size: 32rpx;
background-color: #FFFFFF;
margin-top: 10rpx;
padding-top: 20rpx;
border-radius: 20rpx;
.header {
margin-bottom: 20rpx;
margin-left: 17rpx;
}
.productmodel {
border: 4rpx solid #FFFFFF;
}
.Productmodel {
background: #ECF1FA;
border: 4rpx solid #4C7BC9;
color: #4C7BC9;
}
.productmodel,
.Productmodel {
background-color: #F6F6F6;
height: 300rpx;
text-align: center;
width: 30%;
font-size: 24rpx;
border-radius: 10rpx;
margin: 5rpx 1.5% 10rpx;
padding: 0 0 10rpx;
view {
background-color: #F6F6F6;
margin: 10rpx auto;
width: 98%;
// height: 90rpx;
border-radius: 10rpx;
font-size: 24rpx;
text-overflow: -o-ellipsis-lastline;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
line-clamp: 2;
-webkit-box-orient: vertical;
}
image {
border-radius: 10rpx;
width: 100%;
height: 200rpx;
}
}
} }
} }