This commit is contained in:
2023-10-08 22:53:13 +08:00
parent b883b02fb9
commit e36d60d015
83 changed files with 18303 additions and 9590 deletions

View File

@@ -1,11 +1,10 @@
<template>
<nut-overlay v-model:visible="visible" :close-on-click-overlay="false">
<nut-overlay :visible="visible" :close-on-click-overlay="false">
<view class="text">
<view>授权提醒</view>
<view style="margin-top: 10px"
>请授权头像信息以便为您提供更好的服务
</view
>
>请授权头像信息以便为您提供更好的服务
</view>
<view class="bom">
<view class="btn b" @click="onCancel">随便逛逛</view>
<view class="btn a" @tap="onOk">去授权</view>
@@ -16,53 +15,63 @@
<script setup lang="ts">
// import { computed, ref } from "vue";
import Taro from '@tarojs/taro'
import {login} from '@/api/user'
import Taro from "@tarojs/taro";
import { login } from "@/api/user";
defineProps({
visible: {
type: Boolean,
default: false
}
})
default: false,
},
});
const emit = defineEmits(['update:visible', 'ok'])
const emit = defineEmits(["update:visible", "ok"]);
const onCancel = () => {
emit('update:visible', false)
}
emit("update:visible", false);
};
const onOk = () => {
Taro.showLoading({
title: "正在授权中",
mask: true,
});
Taro.getUserProfile({
desc: '完善用户资料',
desc: "完善用户资料",
success: async (user) => {
Taro.login({
success: async ({code}) => {
success: async ({ code }) => {
try {
const {data}: any = await login({
const { data }: any = await login({
code: code,
nickName: user.userInfo.nickName,
avatarUrl: user.userInfo.avatarUrl
})
Taro.setStorageSync('token', data.token)
emit('ok', false)
avatarUrl: user.userInfo.avatarUrl,
});
Taro.setStorageSync("token", data.token);
emit("ok", false);
} catch (error) {
Taro.showToast({
title: error.message,
icon: 'none'
})
icon: "none",
});
}
},
fail: (err) => {
console.log(err)
}
})
console.log(err);
},
complete: () => {
Taro.hideLoading();
},
});
},
fail: (err) => {
console.log(err)
}
})
}
console.log(err);
},
complete: () => {
Taro.hideLoading();
},
});
};
</script>
<style lang="scss">

View File

@@ -6,7 +6,7 @@
safe-area-inset-bottom
:close-on-click-overlay="false"
:style="{ height: 'auto' }"
v-model:visible="isShowPay"
:visible="isShowPay"
@click-close-icon="closePay"
>
<view class="div">
@@ -46,66 +46,68 @@
</template>
<script setup lang="ts">
import { ref, watch } from "vue";
import { IconFont } from "@nutui/icons-vue-taro";
import Taro from "@tarojs/taro";
import { payOrder } from "@/api/order";
import { payJfOrder } from "@/api/goods";
import { getPersonalInfo } from "@/api/user";
import {ref, watch} from 'vue'
import {IconFont} from '@nutui/icons-vue-taro'
import Taro from '@tarojs/taro'
import {payOrder} from '@/api/order'
import {payJfOrder} from '@/api/goods'
import {getPersonalInfo} from '@/api/user'
const prop = defineProps({
isShowPay: {
required: true,
type: Boolean,
default: false,
default: false
},
payType: {
required: true,
type: String,
default: "wx",
default: 'wx'
},
jfInfo: {
type: Object,
default: () => {
return {};
},
},
});
return {}
}
}
})
const emit = defineEmits(["closePay", "successPay"]);
const emit = defineEmits(['closePay', 'successPay'])
const info = ref<any>({});
const info = ref<{ integral?: any }>({})
watch(
() => prop.isShowPay,
() => {
getInfo();
getInfo()
}
);
)
const getInfo = async () => {
try {
const res = await getPersonalInfo();
info.value = res.data.data;
const res = await getPersonalInfo()
info.value = res.data.data
} catch (error) {
Taro.showToast({
title: error.msg,
icon: "none",
});
icon: 'none'
})
throw error
}
};
}
const goPay = async () => {
console.log(prop.jfInfo)
if (!prop.jfInfo)
return Taro.showToast({
title: "未获取到订单信息",
icon: "none",
});
if (prop.payType === "wx") {
title: '未获取到订单信息',
icon: 'none'
})
if (prop.payType === 'wx') {
try {
const { data } = await payOrder({
oid: prop.jfInfo.oid,
});
const {data} = await payOrder({
oid: prop.jfInfo.oid
})
Taro.requestPayment({
timeStamp: data.data.timeStamp,
nonceStr: data.data.nonceStr,
@@ -114,50 +116,51 @@ const goPay = async () => {
paySign: data.data.paySign,
success: function () {
Taro.showToast({
title: "支付成功",
icon: "success",
duration: 2000,
});
title: '支付成功',
icon: 'success',
duration: 2000
})
Taro.navigateTo({
url: "/pages/hotGoods/hot_list/index",
});
url: '/pages/hotGoods/hot_list/index'
})
},
fail: function () {
Taro.showToast({
title: "支付失败",
icon: "none",
duration: 2000,
});
},
});
emit("closePay", false);
title: '支付失败',
icon: 'none',
duration: 2000
})
}
})
emit('closePay', false)
} catch (e) {
Taro.showToast({
title: e.msg,
icon: "none",
});
icon: 'none'
})
throw e
}
} else {
const res = await payJfOrder(prop.jfInfo);
const res = await payJfOrder(prop.jfInfo)
Taro.showToast({
title: res.msg,
icon: "success",
duration: 2000,
});
icon: 'success',
duration: 2000
})
Taro.navigateTo({
url: "/pages/users/order_list/index",
});
emit("closePay", false);
url: '/pages/users/order_list/index?type=0'
})
emit('closePay', false)
}
};
}
const closePay = () => {
Taro.showToast({
title: "取消支付",
icon: "none",
});
emit("closePay", false);
};
title: '取消支付',
icon: 'none'
})
emit('closePay', false)
}
</script>
<style lang="scss">

View File

@@ -1,381 +1,286 @@
<template>
<view class="container">
<view class="page-body">
<view class="wrapper">
<view
class="toolbar"
@tap="format"
style="max-height: 240px; overflow-y: auto"
>
<!-- 字体 -->
<!-- <view
:class="data.formats.fontFamily ? 'ql-active' : ''"
class="iconfont icon-font"
data-name="fontFamily"
data-value="Pacifico"
></view> -->
<!-- 加粗 -->
<view
:class="data.formats.bold ? 'ql-active' : ''"
class="iconfont icon-zitijiacu"
data-name="bold"
></view>
<!-- 斜体 -->
<view
:class="data.formats.italic ? 'ql-active' : ''"
class="iconfont icon-zitixieti"
data-name="italic"
></view>
<!-- 下划线 -->
<view
:class="data.formats.underline ? 'ql-active' : ''"
class="iconfont icon-zitixiahuaxian"
data-name="underline"
></view>
<!-- 删除中划线 -->
<!-- <view
:class="data.formats.strike ? 'ql-active' : ''"
class="iconfont icon-zitishanchuxian"
data-name="strike"
></view> -->
<!-- 字号 -->
<!-- <view
:class="data.formats.fontSize === '24px' ? 'ql-active' : ''"
class="iconfont icon-font-size"
data-name="fontSize"
data-value="48px"
></view>-->
<!-- 字体颜色 -->
<!-- <view
:class="data.formats.color === '#0000ff' ? 'ql-active' : ''"
class="iconfont icon-font-colors"
data-name="color"
data-value="#0000ff"
></view> -->
<!-- 清除样式 -->
<!-- <view class="iconfont icon-clearformat" @tap="removeFormat"></view> -->
<!-- 对齐方式 -->
<view
:class="data.formats.align === 'left' ? 'ql-active' : ''"
class="iconfont icon-zuoduiqi"
data-name="align"
data-value="left"
></view>
<!-- 对齐方式居中 -->
<view
:class="data.formats.align === 'center' ? 'ql-active' : ''"
class="iconfont icon-juzhongduiqi"
data-name="align"
data-value="center"
></view>
<!-- 对齐方式 -->
<view
:class="data.formats.align === 'right' ? 'ql-active' : ''"
class="iconfont icon-youduiqi"
data-name="align"
data-value="right"
></view>
<!-- 对齐方式两侧 -->
<view
:class="data.formats.align === 'justify' ? 'ql-active' : ''"
class="iconfont icon-zuoyouduiqi"
data-name="align"
data-value="justify"
></view>
<!-- 行高 -->
<!-- <view
:class="data.formats.lineHeight ? 'ql-active' : ''"
class="iconfont icon-line-height"
data-name="lineHeight"
data-value="2"
></view>-->
<!-- 字间距 -->
<!-- <view
:class="data.formats.letterSpacing ? 'ql-active' : ''"
class="iconfont icon-Character-Spacing"
data-name="letterSpacing"
data-value="2em"
></view> -->
<!-- 上边距 -->
<!-- <view
:class="data.formats.marginTop ? 'ql-active' : ''"
class="iconfont icon-duanqianju"
data-name="marginTop"
data-value="40px"
></view> -->
<!-- 下边距 -->
<!-- <view
:class="data.formats.marginBottom ? 'ql-active' : ''"
class="iconfont icon-duanhouju"
data-name="marginBottom"
data-value="40px"
></view> -->
<!-- 日期 -->
<!-- <view class="iconfont icon-date" @tap="insertDate"></view> -->
<!-- 勾选 -->
<!-- <view
class="iconfont icon--checklist"
data-name="list"
data-value="check"
></view> -->
<!-- 有序排列 -->
<view
:class="data.formats.list === 'ordered' ? 'ql-active' : ''"
class="iconfont icon-youxupailie"
data-name="list"
data-value="ordered"
></view>
<!-- 无序排列 -->
<view
:class="data.formats.list === 'bullet' ? 'ql-active' : ''"
class="iconfont icon-wuxupailie"
data-name="list"
data-value="bullet"
></view>
<!-- 取消缩进 -->
<view
class="iconfont icon-outdent"
data-name="indent"
data-value="-1"
></view>
<!-- 缩进 -->
<view
class="iconfont icon-indent"
data-name="indent"
data-value="+1"
></view>
<!-- 添加分割线 -->
<view class="iconfont icon-fengexian" @click="insertDivider"></view>
<!-- 插入图片 -->
<view class="iconfont icon-image" @click="insertImage"></view>
<!-- 设置标题 -->
<view
:class="data.formats.header === 3 ? 'ql-active' : ''"
class="iconfont icon-H"
data-name="header"
:data-value="3"
></view>
<!-- 下标 -->
<view
:class="data.formats.script === 'sub' ? 'ql-active' : ''"
class="iconfont icon-zitixiabiao"
data-name="script"
data-value="sub"
></view>
<!-- 上标 -->
<view
:class="data.formats.script === 'super' ? 'ql-active' : ''"
class="iconfont icon-zitishangbiao"
data-name="script"
data-value="super"
></view>
<!-- 清空 -->
<!-- <view class="iconfont icon-shanchu" @tap="clear"></view> -->
<!-- <view
:class="data.formats.direction === 'rtl' ? 'ql-active' : ''"
class="iconfont icon-direction-rtl"
data-name="direction"
data-value="rtl"
></view> -->
<view class="iconfont icon-undo" @click="undo"></view>
<view class="iconfont icon-redo" @click="redo"></view>
</view>
<view class="editor-wrapper">
<editor
id="editor"
class="ql-container"
:placeholder="data.placeholder"
@statuschange="onStatusChange"
:show-img-resize="true"
@ready="onEditorReady"
@input="getCtx"
:content="content"/>
</view>
</view>
<view class="container">
<view class="page-body">
<view class="wrapper">
<view
class="toolbar"
@click="format"
style="max-height: 240px; overflow-y: auto"
>
<!-- 加粗 -->
<view
:class="data.formats.bold ? 'ql-active' : ''"
class="iconfont icon-zitijiacu"
data-name="bold"
></view>
<!-- 斜体 -->
<view
:class="data.formats.italic ? 'ql-active' : ''"
class="iconfont icon-zitixieti"
data-name="italic"
></view>
<!-- 下划线 -->
<view
:class="data.formats.underline ? 'ql-active' : ''"
class="iconfont icon-zitixiahuaxian"
data-name="underline"
></view>
<!-- 对齐方式 -->
<view
:class="data.formats.align === 'left' ? 'ql-active' : ''"
class="iconfont icon-zuoduiqi"
data-name="align"
data-value="left"
></view>
<!-- 对齐方式居中 -->
<view
:class="data.formats.align === 'center' ? 'ql-active' : ''"
class="iconfont icon-juzhongduiqi"
data-name="align"
data-value="center"
></view>
<!-- 对齐方式 -->
<view
:class="data.formats.align === 'right' ? 'ql-active' : ''"
class="iconfont icon-youduiqi"
data-name="align"
data-value="right"
></view>
<!-- 对齐方式两侧 -->
<view
:class="data.formats.align === 'justify' ? 'ql-active' : ''"
class="iconfont icon-zuoyouduiqi"
data-name="align"
data-value="justify"
></view>
<!-- 有序排列 -->
<view
:class="data.formats.list === 'ordered' ? 'ql-active' : ''"
class="iconfont icon-youxupailie"
data-name="list"
data-value="ordered"
></view>
<!-- 无序排列 -->
<view
:class="data.formats.list === 'bullet' ? 'ql-active' : ''"
class="iconfont icon-wuxupailie"
data-name="list"
data-value="bullet"
></view>
<!-- 取消缩进 -->
<view
class="iconfont icon-outdent"
data-name="indent"
data-value="-1"
></view>
<!-- 缩进 -->
<view
class="iconfont icon-indent"
data-name="indent"
data-value="+1"
></view>
<!-- 添加分割线 -->
<view class="iconfont icon-fengexian" @click="insertDivider"></view>
<!-- 插入图片 -->
<view class="iconfont icon-image" @click="insertImage"></view>
<!-- 设置标题 -->
<view
:class="data.formats.header === 3 ? 'ql-active' : ''"
class="iconfont icon-H"
data-name="header"
:data-value="3"
></view>
<!-- 下标 -->
<view
:class="data.formats.script === 'sub' ? 'ql-active' : ''"
class="iconfont icon-zitixiabiao"
data-name="script"
data-value="sub"
></view>
<!-- 上标 -->
<view
:class="data.formats.script === 'super' ? 'ql-active' : ''"
class="iconfont icon-zitishangbiao"
data-name="script"
data-value="super"
></view>
<view class="iconfont icon-undo" @click="undo"></view>
<view class="iconfont icon-redo" @click="redo"></view>
</view>
<view class="editor-wrapper">
<editor
id="editor"
class="ql-container"
:placeholder="data.placeholder"
@statuschange="onStatusChange"
:show-img-resize="true"
@ready="onEditorReady"
@input="getCtx"
/>
</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import {reactive} from 'vue'
import Taro from '@tarojs/taro'
import {BASE_URL} from '@/utils/request'
const {content} = defineProps<{
content: string;
content: string;
}>()
let emits = defineEmits(['input'])
const data = reactive<any>({
editorCtx: '',
readOnly: false,
placeholder: '开始输入...',
richText: '',
formats: {}
editorCtx: '',
readOnly: false,
placeholder: '请输入商品详情...',
richText: '',
formats: {}
})
function onEditorReady() {
// 富文本节点渲染完成
Taro
.createSelectorQuery()
.select('#editor')
.context((res) => {
data.editorCtx = res.context
// 初始化数据
if (content) {
data.editorCtx.setContents({
html: content
})
}
})
.exec()
// 富文本节点渲染完成
Taro
.createSelectorQuery()
.select('#editor')
.context((res) => {
data.editorCtx = res.context
// 初始化数据
if (content) {
data.editorCtx.setContents({
html: content
})
}
})
.exec()
}
// 失去焦点时,获取富文本的内容
function getCtx(e: any) {
data.richText = e.detail.html
emits('input', e.detail.html)
function getCtx(e: { detail: { html: any; }; }) {
data.richText = e.detail.html
emits('input', e.detail.html)
}
// 撤销操作
function undo() {
data.editorCtx.undo()
data.editorCtx.undo()
}
// 复原操作
function redo() {
data.editorCtx.redo()
data.editorCtx.redo()
}
//修改样式
function format(e) {
// console.log("format", e.target.dataset);
let {name, value} = e.target.dataset
if (!name) return
data.editorCtx.format(name, value)
function format(e: { target: { dataset: { name: any; value: any; }; }; }) {
// console.log("format", e.target.dataset);
let {name, value} = e.target.dataset
if (!name) return
data.editorCtx.format(name, value)
}
//通过 Context 方法改变编辑器内样式时触发,返回选区已设置的样式
function onStatusChange(e) {
data.formats = e.detail
function onStatusChange(e: { detail: any; }) {
data.formats = e.detail
}
// 插入分割线
function insertDivider() {
data.editorCtx.insertDivider()
data.editorCtx.insertDivider()
}
// 插入图片
function insertImage() {
Taro.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
Taro.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
// 上传图片的逻辑各有不同,自行调整即可
Taro.uploadFile({
url: `${BASE_URL}/upload`,
name: 'file',
header: {token: Taro.getStorageSync('token')},
filePath: res.tempFilePaths[0],
success: (res) => {
// 上传图片的逻辑各有不同,自行调整即可
Taro.uploadFile({
url: `/system/v1/upload`,
name: 'file',
header: {Authorization: 'token'},
filePath: res.tempFilePaths[0],
success: (res) => {
const imgData = JSON.parse(res.data) as {
code: number;
msg: string;
success: boolean;
}
if (imgData.code === 200) {
// 将图片展示在编辑器中
data.editorCtx.insertImage({
width: '20%', //设置宽度为100%防止宽度溢出手机屏幕
height: 'auto',
src: imgData.msg,
alt: '图像',
success: function () {
console.log('insert image success')
}
})
} else {
console.log('上传失败')
}
},
fail: (err) => {
console.log(err)
}
console.log(res)
const imgData = JSON.parse(res.data) as {
code: number;
msg: string;
data: any;
}
if (imgData.code === 200) {
// 将图片展示在编辑器中
data.editorCtx.insertImage({
width: '100%',
height: 'auto',
src: imgData.data.data,
alt: '图像',
success: function () {
console.log('insert image success')
}
})
} else {
console.log('上传失败')
}
},
fail: (err) => {
console.log(err)
}
})
})
}
})
}
// 清空编辑器内容
// function clear() {
// data.editorCtx.clear({
// success: function (res) {
// console.log("clear success");
// },
// });
// }
// 清除当前选区的样式
// function removeFormat() {
// data.editorCtx.removeFormat();
// }
// 选择日期
// function insertDate() {
// const date = new Date();
// const formatDate = `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`;
// data.editorCtx.insertText({
// text: formatDate
// });
// }
</script>
<style lang="scss" scoped>
@import "//at.alicdn.com/t/c/font_4211210_2x20brbrv94.css";
.page-body {
// height: calc(100vh - var(--window-top) - var(--status-bar-height));
}
<style lang="scss">
@import "../static/font_4211210_2x20brbrv94.css";
.wrapper {
height: 100%;
height: 100%;
}
.editor-wrapper {
height: calc(
100vh - var(--window-top) - var(--status-bar-height) - 280px - 650px
);
overflow: scroll;
background: rgba(153, 153, 153, 0.05);
border-radius: 20px;
margin: 20px 0;
height: calc(
100vh - var(--window-top) - var(--status-bar-height) - 280px - 650px
);
overflow: scroll;
background: rgba(153, 153, 153, 0.05);
border-radius: 20px;
margin: 20px 0;
color: #000;
}
.iconfont {
display: inline-block;
margin: 20px 20px;
width: 32px;
height: 32px;
cursor: pointer;
font-size: 32px;
display: inline-block;
margin: 20px 20px;
width: 32px;
height: 32px;
cursor: pointer;
font-size: 32px;
}
.toolbar {
box-sizing: border-box;
border-bottom: 0;
font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif;
box-sizing: border-box;
border-bottom: 0;
font-family: "Helvetica Neue", "Helvetica", "Arial", sans-serif;
}
.ql-container {
box-sizing: border-box;
padding: 24px 30px;
width: 100%;
min-height: 30vh;
height: 100%;
font-size: 28px;
line-height: 1.5;
box-sizing: border-box;
padding: 24px 30px;
width: 100%;
min-height: 30vh;
height: 100%;
font-size: 28px;
line-height: 1.5;
}
.ql-active {
color: #f38e48;
color: #f38e48;
}
</style>

178
src/components/Ucharts.vue Normal file
View File

@@ -0,0 +1,178 @@
<template>
<canvas
v-if="canvasId"
:id="canvasId"
:canvasId="canvasId"
:style="{
// width: (cWidth / cWidth) * sysInfo.windowWidth + 'px',
width: cWidth,
height: 250 + 'px',
transform: 'scale(' + 1 / pixelRatio + ')',
marginLeft: (cWidth * (pixelRatio - 1)) / 2 + 'px',
marginTop: (cHeight * (pixelRatio - 1)) / 2 + 'px',
}"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
@error="error"
>
</canvas>
</template>
<script setup lang="ts" name="ucharts">
import uCharts from "../utils/js_sdk/u-charts.min.js";
import Taro from "@tarojs/taro";
const canvases = {};
const props = defineProps({
chartType: {
required: true,
type: String,
default: "column",
},
opts: {
required: true,
type: Object,
default() {
return null;
},
},
canvasId: {
type: String,
default: "u-canvas",
},
cWidth: {
default: 350,
},
cHeight: {
default: 250,
},
pixelRatio: {
type: Number,
default: 1,
},
});
Taro.useLoad(() => {
init();
});
const init = () => {
switch (props.chartType) {
case "column":
initColumnChart();
break;
case "line":
initLineChart();
break;
default:
break;
}
};
const initColumnChart = () => {
const ctx = Taro.createCanvasContext(props.canvasId);
canvases[props.canvasId] = new uCharts({
context: ctx,
type: "column",
fontSize: 11,
background: "#FFFFFF",
pixelRatio: props.pixelRatio,
animation: true,
categories: props.opts.categories,
series: props.opts.series,
enableScroll: true,
width: props.cWidth,
height: props.cHeight,
padding: [15,15,0,5],
legend: {},
xAxis: {
disableGrid: true,
},
yAxis: {
data: [
{
min: 0,
},
],
},
extra: {
column: {
type: "group",
width: 30,
activeBgColor: "#000000",
activeBgOpacity: 0.08,
},
},
});
};
const initLineChart = () => {
const ctx = Taro.createCanvasContext(props.canvasId);
canvases[props.canvasId] = new uCharts({
context: ctx,
type: "line",
fontSize: 11,
legend: true,
dataLabel: false,
dataPointShape: true,
background: "#FFFFFF",
pixelRatio: props.pixelRatio,
categories: props.opts.categories,
series: props.opts.series,
animation: true,
enableScroll: true,
xAxis: {
// type: "grid",
// gridColor: "#CCCCCC",
// gridType: "dash",
// dashLength: 8,
// itemCount: 4,
scrollShow: true,
disableGrid: true,
},
yAxis: {
gridType: "dash",
gridColor: "#CCCCCC",
dashLength: 8,
splitNumber: 5,
min: 10,
max: 180,
format: (val) => {
return val.toFixed(0) + "元";
},
},
width: props.cWidth * props.pixelRatio,
height: props.cHeight * props.pixelRatio,
extra: {
line: {
type: "straight",
},
},
});
};
const touchStart = (e: any) => {
canvases[props.canvasId].showToolTip(e, {
format: function (item: any, category: any) {
return category + " " + item.name + ":" + item.data;
},
});
canvases[props.canvasId].scrollStart(e);
};
const touchMove = (e: any) => {
canvases[props.canvasId].scroll(e);
};
const touchEnd = (e: any) => {
canvases[props.canvasId].scrollEnd(e);
};
const error = (e: any) => {
throw e;
};
</script>
<style lang="scss"></style>

View File

@@ -1,62 +1,61 @@
<template>
<view>
<nut-uploader
v-model:file-list="fileList"
:url="config.url"
:maximum="max"
:headers="config.headers"
@success="success"
@failure="failure"
:multiple="false"
></nut-uploader>
</view>
<nut-uploader
v-model:file-list="fileList"
:url="config.url"
:maximum="max"
:headers="config.headers"
@success="success"
@failure="failure"
:multiple="false"
>
</nut-uploader>
</template>
<script setup lang="ts">
import { BASE_URL } from "@/utils/request";
import { computed, ref } from "vue";
import Taro from "@tarojs/taro";
import {BASE_URL} from '@/utils/request'
import {computed, ref} from 'vue'
import Taro from '@tarojs/taro'
const props = defineProps({
list: {
type: Array,
default: () => [],
default: () => []
},
max: {
type: Number,
default: 1,
},
});
default: 1
}
})
const emits = defineEmits(["update:list"]);
const emits = defineEmits(['update:list'])
const fileList = computed({
get: () => props.list,
set: (val) => emits("update:list", val),
});
set: (val) => emits('update:list', val)
})
const config = ref({
url: `${BASE_URL}/upload`,
headers: {
token: Taro.getStorageSync("token"),
},
});
token: Taro.getStorageSync('token')
}
})
const success = (res: any) => {
const data = JSON.parse(res.responseText.data);
res.fileItem.url = data.data.data;
const data = JSON.parse(res.responseText.data)
res.fileItem.url = data.data.data
Taro.showToast({
title: "上传成功",
icon: "success",
});
};
title: '上传成功',
icon: 'success'
})
}
const failure = () => {
Taro.showToast({
title: "上传失败",
icon: "error",
});
};
title: '上传失败',
icon: 'error'
})
}
</script>
<style lang="scss"></style>

View File

@@ -1,15 +1,328 @@
<script lang="ts">
import {defineComponent} from 'vue'
<script lang="ts" setup>
import { computed, ref } from "vue";
import Taro from "@tarojs/taro";
import headImg from "../static/def_avatar.png";
import logoImg from "../static/logo.jpg";
import { BASE_URL } from "@/utils/request";
import { getPhone, login } from "@/api/user";
export default defineComponent({
name: "UserModal"
})
const props = defineProps({
isShow: {
type: Boolean,
default: false,
},
});
const emits = defineEmits(["closeEdit", "update:isShow"]);
const userInfo = ref({
nickname: "",
avatar: "",
phone: "",
});
const show = computed({
get: (): boolean => props.isShow,
set: (val) => {
emits("update:isShow", val);
},
});
const mp_is_new = ref(true);
const canvasStatus = ref(false);
const closeAttr = () => {
emits("closeEdit");
};
const onChooseAvatar = (e) => {
const { avatarUrl } = e.detail;
console.log(avatarUrl);
Taro.uploadFile({
url: `${BASE_URL}/upload`,
filePath: avatarUrl,
name: "file",
success: function (res) {
const data = JSON.parse(res.data);
userInfo.value.avatar = data.data.data;
},
});
};
const uploadPic = () => {
canvasStatus.value = true;
};
const getPhoneNumber = async (e: any) => {
Taro.showLoading({
title: "授权手机号中",
mask: true,
});
const { code } = e.detail;
const res = await getPhone({
code: code,
});
userInfo.value.phone = res.data.phone;
Taro.hideLoading();
};
const formSubmit = async (e: any) => {
if (!userInfo.value.avatar)
return Taro.showToast({
title: "请上传头像",
icon: "none",
});
userInfo.value.nickname = e.detail.value.nickname;
if (!userInfo.value.nickname)
return Taro.showToast({
title: "请输入昵称",
icon: "none",
});
if (!userInfo.value.phone)
return Taro.showToast({
title: "请授权手机号码",
icon: "none",
});
const res = await login({
Code: Taro.getStorageSync("wx_code"),
NickName: userInfo.value.nickname,
AvatarUrl: userInfo.value.avatar,
Phone: userInfo.value.phone,
Referee: Taro.getStorageSync("bind_id") || "",
});
emits("closeEdit");
Taro.showToast({
title: res.msg,
icon: "success",
duration: 2000,
});
Taro.setStorageSync("token", res.data.token);
setTimeout(() => {
Taro.removeStorageSync("wx_code");
Taro.removeStorageSync("bind_id");
Taro.switchTab({
url: "/pages/user/index",
});
}, 2000);
};
</script>
<template>
$END$
<view>
<nut-popup
position="bottom"
safe-area-inset-bottom
closeable
:style="{ padding: '20px 10px' }"
v-model:visible="show"
@close="closeAttr"
:close-on-click-overlay="false"
>
<view class="mp-data">
<image class="image" :src="logoImg"></image>
<text class="mp-name">捷兑通 申请</text>
</view>
<view class="trip-msg">
<view class="title"> 获取您的昵称头像 </view>
<view class="trip"> 提供具有辨识度的用户中心界面 </view>
</view>
<form @submit="formSubmit">
<view class="edit">
<view class="avatar edit-box">
<view class="left">
<view class="head">头像</view>
<view
class="avatar-box"
v-if="!mp_is_new"
@click.stop="uploadPic"
>
<image
:src="userInfo.avatar || headImg"
mode="aspectFill"
></image>
</view>
<button
v-else
class="avatar-box"
open-type="chooseAvatar"
@chooseavatar="onChooseAvatar"
>
<image
:src="userInfo.avatar || headImg"
mode="aspectFill"
></image>
</button>
</view>
</view>
<view class="nickname edit-box">
<view class="left">
<view class="head">昵称</view>
<view class="input">
<input
type="nickname"
placeholder-class="pl-sty"
placeholder="请输入昵称"
name="nickname"
:maxlength="16"
:value="userInfo.nickname"
/>
</view>
</view>
</view>
<view class="nickname edit-box">
<view class="left">
<view class="head">号码</view>
<view class="input">
<button
open-type="getPhoneNumber"
@getphonenumber="getPhoneNumber"
>
{{
!userInfo.phone
? "请授权手机号"
: "授权成功"
}}
</button>
</view>
</view>
</view>
</view>
<view class="bottom">
<nut-button
formType="submit"
block
type="success"
color="#07C160"
>
保存
</nut-button>
</view>
</form>
</nut-popup>
</view>
</template>
<style scoped lang="scss">
<style lang="scss">
.mp-data {
display: flex;
align-items: center;
margin-bottom: 30px;
</style>
.mp-name {
font-size: 28px;
font-weight: bold;
color: #000000;
}
.image {
width: 48px;
height: 48px;
border-radius: 50%;
margin-right: 16px;
}
}
.trip-msg {
padding-bottom: 32px;
border-bottom: 1px solid #f5f5f5;
.title {
font-size: 30px;
font-weight: bold;
color: #000;
margin-bottom: 6px;
}
.trip {
font-size: 26px;
color: #777777;
}
}
.edit {
// border-bottom: 1px solid #f5f5f5;
.avatar {
border-bottom: 1px solid #f5f5f5;
}
.nickname {
.input {
width: 100%;
}
border-bottom: 1px solid #f5f5f5;
}
input {
height: 80px;
}
button {
flex: 1;
display: flex;
align-items: center;
background: none;
padding: 0;
height: 50px;
font-size: 28px;
color: #838383;
&::after {
border: none;
}
}
}
.edit-box {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 30px;
padding: 22px 0;
.left {
display: flex;
align-items: center;
flex: 1;
.head {
color: rgba(0, 0, 0, 0.9);
white-space: nowrap;
margin-right: 60px;
}
.avatar-box {
image {
width: 100px;
height: 100%;
border-radius: 6px;
}
}
button {
flex: 1;
display: flex;
align-items: center;
background: none;
height: 100px;
&::after {
border: none;
}
}
}
}
.icon-xiangyou {
color: #cfcfcf;
}
.bottom {
margin-top: 20px;
padding: 0 150px;
.nut-button {
border-radius: 10px;
}
}
</style>