feat: add mini-program privacy auth, update oss urls and refine photo guide
update oss static resource urls to oss.nianxx.cn refactor privacy component to be reusable, add wechat mini-program privacy authorization check before image picking add image urls to photo guide examples, refine photo guide ui styles and remove unused avatarSrc prop
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="privacy" v-if="showPrivacy">
|
<view v-if="visible" class="privacy">
|
||||||
<view class="content">
|
<view class="content">
|
||||||
<view class="title">隐私保护指引</view>
|
<view class="title">隐私保护指引</view>
|
||||||
<view class="des">
|
<view class="des">
|
||||||
请您仔细阅读并充分理解<text
|
请您仔细阅读并充分理解<text
|
||||||
class="link"
|
class="link"
|
||||||
@click="handleOpenPrivacyContract"
|
@click="handleOpenPrivacyContract"
|
||||||
>{{ privacyContractName }}</text
|
>{{ contractName }}</text
|
||||||
>
|
>
|
||||||
,如您同意前述协议的全部内容,请点击“同意”开始使用。<text class="cancel"
|
,如您同意前述协议的全部内容,请点击“同意”开始使用。<text class="cancel"
|
||||||
>如您不同意,将被限制使用部分功能,或将在您使用具体功能前再次询问以取得您的授权同意。</text
|
>如您不同意,将被限制使用部分功能,或将在您使用具体功能前再次询问以取得您的授权同意。</text
|
||||||
@@ -28,46 +28,27 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from "vue";
|
defineProps({
|
||||||
import { onShow } from "@dcloudio/uni-app";
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
const showPrivacy = ref(false);
|
default: false,
|
||||||
const privacyContractName = ref("隐私保护指引");
|
},
|
||||||
|
contractName: {
|
||||||
onShow(() => {
|
type: String,
|
||||||
// 条件编译微信小程序
|
default: "隐私保护指引",
|
||||||
// #ifdef MP-WEIXIN
|
},
|
||||||
|
|
||||||
wx.getPrivacySetting({
|
|
||||||
success: (res) => {
|
|
||||||
console.log("cj隐私配置", res);
|
|
||||||
if (res.errMsg == "getPrivacySetting:ok") {
|
|
||||||
privacyContractName.value = res.privacyContractName;
|
|
||||||
showPrivacy.value = !!res.needAuthorization;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// 条件编译抖音小程序
|
|
||||||
// #ifdef MP-TOUTIAO
|
|
||||||
uni.getPrivacySetting({
|
|
||||||
success: (res) => {
|
|
||||||
console.log(res);
|
|
||||||
showPrivacy.value = !!res.needAuthorization;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
// #endif
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(["agree", "disagree"]);
|
||||||
|
|
||||||
// 拒绝
|
// 拒绝
|
||||||
const handleDisagree = () => {
|
const handleDisagree = () => {
|
||||||
showPrivacy.value = false;
|
emit("disagree");
|
||||||
};
|
};
|
||||||
|
|
||||||
// 同意
|
// 同意
|
||||||
const handleAgreePrivacyAuthorization = () => {
|
const handleAgreePrivacyAuthorization = () => {
|
||||||
showPrivacy.value = false;
|
emit("agree");
|
||||||
};
|
};
|
||||||
|
|
||||||
// 打开隐私保护指引
|
// 打开隐私保护指引
|
||||||
|
|||||||
@@ -1,56 +1,42 @@
|
|||||||
<template>
|
<template>
|
||||||
<uni-popup
|
<uni-popup ref="popupRef" type="bottom" background-color="transparent" mask-background-color="rgba(0, 0, 0, 0)"
|
||||||
ref="popupRef"
|
:safe-area="false" :is-mask-click="false">
|
||||||
type="bottom"
|
|
||||||
background-color="transparent"
|
|
||||||
mask-background-color="rgba(0, 0, 0, 0)"
|
|
||||||
:safe-area="false"
|
|
||||||
:is-mask-click="false"
|
|
||||||
>
|
|
||||||
<view class="photo-guide-panel">
|
<view class="photo-guide-panel">
|
||||||
<view class="photo-guide-close" @tap="emit('close')">
|
<view class="photo-guide-close" @tap="emit('close')">
|
||||||
<uni-icons type="closeempty" size="30" color="#8fa2ba" />
|
<uni-icons type="closeempty" size="30" color="#8fa2ba" />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<text class="photo-guide-title">选图说明</text>
|
<text class="photo-guide-title">选图说明</text>
|
||||||
|
|
||||||
<view class="photo-guide-section">
|
<view class="photo-guide-section">
|
||||||
<text class="photo-guide-section-title">正确照片示例</text>
|
<text class="photo-guide-section-title">正确照片示例</text>
|
||||||
<view class="photo-guide-grid">
|
<view class="photo-guide-grid">
|
||||||
<view
|
<view v-for="item in positiveExamples" :key="item.id" class="photo-example-card is-positive"
|
||||||
v-for="item in positiveExamples"
|
:class="`example-${item.variant}`">
|
||||||
:key="item.id"
|
<view class="photo-example-thumb">
|
||||||
class="photo-example-card is-positive"
|
<image class="photo-example-image" :src="item.imageUrl" mode="aspectFill" />
|
||||||
:class="`example-${item.variant}`"
|
</view>
|
||||||
>
|
<text class="photo-example-caption">{{ item.label }}</text>
|
||||||
<view class="photo-example-thumb">
|
|
||||||
<image class="photo-example-image" :src="avatarSrc" mode="aspectFill" />
|
|
||||||
</view>
|
</view>
|
||||||
<text class="photo-example-caption">{{ item.label }}</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="photo-guide-section">
|
<view class="photo-guide-section">
|
||||||
<text class="photo-guide-section-title">错误照片示例</text>
|
<text class="photo-guide-section-title">错误照片示例</text>
|
||||||
<view class="photo-guide-grid">
|
<view class="photo-guide-grid">
|
||||||
<view
|
<view v-for="item in negativeExamples" :key="item.id" class="photo-example-card is-negative"
|
||||||
v-for="item in negativeExamples"
|
:class="`example-${item.variant}`">
|
||||||
:key="item.id"
|
<view class="photo-example-thumb">
|
||||||
class="photo-example-card is-negative"
|
<image class="photo-example-image" :src="item.imageUrl" mode="aspectFill" />
|
||||||
:class="`example-${item.variant}`"
|
</view>
|
||||||
>
|
<text class="photo-example-caption">{{ item.label }}</text>
|
||||||
<view class="photo-example-thumb">
|
|
||||||
<image class="photo-example-image" :src="avatarSrc" mode="aspectFill" />
|
|
||||||
</view>
|
</view>
|
||||||
<text class="photo-example-caption">{{ item.label }}</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="photo-guide-primary" @tap="emit('confirm')">
|
<view class="photo-guide-primary" @tap="emit('confirm')">
|
||||||
我已了解,开始选图
|
我已了解,开始选图
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</uni-popup>
|
</uni-popup>
|
||||||
</template>
|
</template>
|
||||||
@@ -59,10 +45,6 @@
|
|||||||
import { nextTick, onMounted, ref } from "vue";
|
import { nextTick, onMounted, ref } from "vue";
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
avatarSrc: {
|
|
||||||
type: String,
|
|
||||||
default: "",
|
|
||||||
},
|
|
||||||
positiveExamples: {
|
positiveExamples: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
.photo-guide-grid {
|
.photo-guide-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
gap: 16px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-example-card {
|
.photo-example-card {
|
||||||
@@ -59,34 +59,29 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.photo-example-thumb {
|
.photo-example-thumb {
|
||||||
width: 74px;
|
width: 80px;
|
||||||
height: 74px;
|
height: 80px;
|
||||||
display: block;
|
display: block;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
border-radius: 12px;
|
border: 2px solid transparent;
|
||||||
|
border-radius: 14px;
|
||||||
background: #f2f4f7;
|
background: #f2f4f7;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-example-image {
|
.photo-example-image {
|
||||||
width: 98px;
|
width: 100%;
|
||||||
height: 150px;
|
height: 100%;
|
||||||
display: block;
|
display: block;
|
||||||
margin: -24px 0 0 -12px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.example-scene .photo-example-image,
|
.is-positive .photo-example-thumb {
|
||||||
.example-group .photo-example-image {
|
border-color: rgba(22, 191, 118, 0.34);
|
||||||
width: 112px;
|
|
||||||
margin-left: -18px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.example-blur .photo-example-image {
|
.is-negative .photo-example-thumb {
|
||||||
filter: blur(1.6px);
|
border-color: rgba(255, 80, 79, 0.34);
|
||||||
}
|
|
||||||
|
|
||||||
.example-cover .photo-example-image {
|
|
||||||
transform: translateY(8px) scale(1.08);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.photo-example-caption {
|
.photo-example-caption {
|
||||||
|
|||||||
@@ -3,16 +3,19 @@ export const positiveExamples = [
|
|||||||
id: "portrait",
|
id: "portrait",
|
||||||
label: "单人正脸",
|
label: "单人正脸",
|
||||||
variant: "portrait",
|
variant: "portrait",
|
||||||
|
imageUrl: "https://oss.nianxx.cn/mp/static/xiaoqi/1.png",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "smile",
|
id: "smile",
|
||||||
label: "表情自然",
|
label: "表情自然",
|
||||||
variant: "smile",
|
variant: "smile",
|
||||||
|
imageUrl: "https://oss.nianxx.cn/mp/static/xiaoqi/2.png",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "scene",
|
id: "scene",
|
||||||
label: "背景干净",
|
label: "背景干净",
|
||||||
variant: "scene",
|
variant: "scene",
|
||||||
|
imageUrl: "https://oss.nianxx.cn/mp/static/xiaoqi/3.png",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -21,15 +24,18 @@ export const negativeExamples = [
|
|||||||
id: "blur",
|
id: "blur",
|
||||||
label: "非清晰正脸",
|
label: "非清晰正脸",
|
||||||
variant: "blur",
|
variant: "blur",
|
||||||
|
imageUrl: "https://oss.nianxx.cn/mp/static/xiaoqi/4.png",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "cover",
|
id: "cover",
|
||||||
label: "面部有遮挡",
|
label: "面部有遮挡",
|
||||||
variant: "cover",
|
variant: "cover",
|
||||||
|
imageUrl: "https://oss.nianxx.cn/mp/static/xiaoqi/5.png",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "group",
|
id: "group",
|
||||||
label: "多人合照",
|
label: "多人合照",
|
||||||
variant: "group",
|
variant: "group",
|
||||||
|
imageUrl: "https://oss.nianxx.cn/mp/static/xiaoqi/6.png",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,37 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="aigc-use-template-page">
|
<view class="aigc-use-template-page">
|
||||||
<AigcTopBar
|
<AigcTopBar :points="pointBalance" recharge-label="充值" @back="handleBack" @history="handleHistory"
|
||||||
:points="pointBalance"
|
@recharge="handleRecharge" />
|
||||||
recharge-label="充值"
|
|
||||||
@back="handleBack"
|
|
||||||
@history="handleHistory"
|
|
||||||
@recharge="handleRecharge"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<view class="aigc-use-template-body">
|
<view class="aigc-use-template-body">
|
||||||
<view class="aigc-use-template-content">
|
<view class="aigc-use-template-content">
|
||||||
<TemplateVersionHero :template="currentTemplate" />
|
<TemplateVersionHero :template="currentTemplate" />
|
||||||
|
|
||||||
<GenerateConfirmPanel
|
<GenerateConfirmPanel v-if="currentStep === 'generateConfirm'" :cost="currentCost" :balance="pointBalance"
|
||||||
v-if="currentStep === 'generateConfirm'"
|
@generate="handleGenerate" @recharge="handleRecharge" />
|
||||||
:cost="currentCost"
|
<GeneratingProgressPanel v-else-if="currentStep === 'generating'" :cost="currentCost" :progress="8"
|
||||||
:balance="pointBalance"
|
@complete="handleGenerateComplete" />
|
||||||
@generate="handleGenerate"
|
|
||||||
@recharge="handleRecharge"
|
|
||||||
/>
|
|
||||||
<GeneratingProgressPanel
|
|
||||||
v-else-if="currentStep === 'generating'"
|
|
||||||
:cost="currentCost"
|
|
||||||
:progress="8"
|
|
||||||
@complete="handleGenerateComplete"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<VersionOptionList
|
<VersionOptionList :options="templateItems" :selected-value="selectedTemplateItemId"
|
||||||
:options="templateItems"
|
@select="handleSelectTemplateItem" />
|
||||||
:selected-value="selectedTemplateItemId"
|
|
||||||
@select="handleSelectTemplateItem"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<text class="aigc-use-template-note">
|
<text class="aigc-use-template-note">
|
||||||
动效视频版会先生图,再升级为 5 秒内动效视频。
|
动效视频版会先生图,再升级为 5 秒内动效视频。
|
||||||
@@ -41,42 +24,28 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view v-if="currentStep === 'uploadGuide'" class="aigc-use-template-popup-host">
|
<view v-if="currentStep === 'uploadGuide'" class="aigc-use-template-popup-host">
|
||||||
<PhotoGuidePanel
|
<PhotoGuidePanel :positive-examples="positiveExamples" :negative-examples="negativeExamples"
|
||||||
:avatar-src="guideAvatar"
|
@close="handleCloseGuide" @confirm="handleConfirmGuide" />
|
||||||
:positive-examples="positiveExamples"
|
|
||||||
:negative-examples="negativeExamples"
|
|
||||||
@close="handleCloseGuide"
|
|
||||||
@confirm="handleConfirmGuide"
|
|
||||||
/>
|
|
||||||
</view>
|
</view>
|
||||||
<view v-if="currentStep === 'photoPick'" class="aigc-use-template-popup-host">
|
<view v-if="currentStep === 'photoPick'" class="aigc-use-template-popup-host">
|
||||||
<PhotoPickDrawer
|
<PhotoPickDrawer :loading="isUploading" @close="handleCloseGuide" @camera="handlePickCamera"
|
||||||
:loading="isUploading"
|
@album="handlePickAlbum" />
|
||||||
@close="handleCloseGuide"
|
|
||||||
@camera="handlePickCamera"
|
|
||||||
@album="handlePickAlbum"
|
|
||||||
/>
|
|
||||||
</view>
|
</view>
|
||||||
<view v-if="currentStep === 'photoConfirm'" class="aigc-use-template-popup-host">
|
<view v-if="currentStep === 'photoConfirm'" class="aigc-use-template-popup-host">
|
||||||
<PhotoConfirmDrawer
|
<PhotoConfirmDrawer :avatar-src="selectedImageLocalPath || guideAvatar" @close="handleClosePhotoConfirm"
|
||||||
:avatar-src="selectedImageLocalPath || guideAvatar"
|
@confirm="handleConfirmPhoto" />
|
||||||
@close="handleClosePhotoConfirm"
|
|
||||||
@confirm="handleConfirmPhoto"
|
|
||||||
/>
|
|
||||||
</view>
|
</view>
|
||||||
<PointInsufficientDialog
|
<PointInsufficientDialog v-if="pointDialogVisible" :cost="currentCost" :balance="pointBalance"
|
||||||
v-if="pointDialogVisible"
|
@cancel="handleClosePointDialog" @recharge="handlePointRecharge" />
|
||||||
:cost="currentCost"
|
<Privacy :visible="privacyVisible" :contract-name="privacyContractName" @agree="handlePrivacyAgree"
|
||||||
:balance="pointBalance"
|
@disagree="handlePrivacyDisagree" />
|
||||||
@cancel="handleClosePointDialog"
|
|
||||||
@recharge="handlePointRecharge"
|
|
||||||
/>
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, ref } from "vue";
|
import { computed, ref } from "vue";
|
||||||
import { onLoad, onShow } from "@dcloudio/uni-app";
|
import { onLoad, onShow } from "@dcloudio/uni-app";
|
||||||
|
import Privacy from "@/components/Privacy/index.vue";
|
||||||
import AigcTopBar from "@/pages-aigc/components/AigcTopBar/index.vue";
|
import AigcTopBar from "@/pages-aigc/components/AigcTopBar/index.vue";
|
||||||
import { useCurrentCredit } from "@/pages-aigc/hooks/useCurrentCredit.js";
|
import { useCurrentCredit } from "@/pages-aigc/hooks/useCurrentCredit.js";
|
||||||
import {
|
import {
|
||||||
@@ -108,6 +77,9 @@ const currentStep = ref("version");
|
|||||||
const pointDialogVisible = ref(false);
|
const pointDialogVisible = ref(false);
|
||||||
const isUploading = ref(false);
|
const isUploading = ref(false);
|
||||||
const isCreatingTask = ref(false);
|
const isCreatingTask = ref(false);
|
||||||
|
const privacyVisible = ref(false);
|
||||||
|
const privacyContractName = ref("隐私保护指引");
|
||||||
|
const pendingImageSourceType = ref("");
|
||||||
|
|
||||||
const currentTemplate = computed(() => {
|
const currentTemplate = computed(() => {
|
||||||
return templates.value.find((item) => item.templateId === templateId.value) || templates.value[0] || {};
|
return templates.value.find((item) => item.templateId === templateId.value) || templates.value[0] || {};
|
||||||
@@ -294,9 +266,47 @@ const chooseImageWithSource = (sourceType) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const chooseAndUploadImage = (sourceType) => {
|
const chooseAndUploadImage = (sourceType) => {
|
||||||
if (isUploading.value) return;
|
if (isUploading.value || pendingImageSourceType.value) return;
|
||||||
|
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
pendingImageSourceType.value = sourceType;
|
||||||
|
wx.getPrivacySetting({
|
||||||
|
success: (res) => {
|
||||||
|
if (res?.needAuthorization) {
|
||||||
|
privacyContractName.value = res.privacyContractName || "隐私保护指引";
|
||||||
|
privacyVisible.value = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pendingImageSourceType.value = "";
|
||||||
|
chooseImageWithSource(sourceType);
|
||||||
|
},
|
||||||
|
fail: (error) => {
|
||||||
|
pendingImageSourceType.value = "";
|
||||||
|
console.warn("检查微信隐私授权失败", error);
|
||||||
|
showPlaceholderToast("隐私授权检查失败");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifndef MP-WEIXIN
|
||||||
chooseImageWithSource(sourceType);
|
chooseImageWithSource(sourceType);
|
||||||
|
// #endif
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePrivacyAgree = () => {
|
||||||
|
const sourceType = pendingImageSourceType.value;
|
||||||
|
privacyVisible.value = false;
|
||||||
|
pendingImageSourceType.value = "";
|
||||||
|
|
||||||
|
if (sourceType) {
|
||||||
|
chooseImageWithSource(sourceType);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePrivacyDisagree = () => {
|
||||||
|
privacyVisible.value = false;
|
||||||
|
pendingImageSourceType.value = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePickCamera = () => {
|
const handlePickCamera = () => {
|
||||||
|
|||||||
@@ -10,10 +10,9 @@ export const devUrl = "https://onefeel.brother7.cn/ingress";
|
|||||||
/// 测试服务器wss地址
|
/// 测试服务器wss地址
|
||||||
export const wssDevUrl = "wss://onefeel.brother7.cn/ingress/agent/ws/chat";
|
export const wssDevUrl = "wss://onefeel.brother7.cn/ingress/agent/ws/chat";
|
||||||
|
|
||||||
|
|
||||||
/// 服务器基础地址 - 根据环境变量自动切换
|
/// 服务器基础地址 - 根据环境变量自动切换
|
||||||
import { currentClientType } from "@/constant/base";
|
import { currentClientType } from "@/constant/base";
|
||||||
export const ossChengduUrl = () => {
|
export const ossChengduUrl = () => {
|
||||||
const clientType = currentClientType().toLowerCase();
|
const clientType = currentClientType().toLowerCase();
|
||||||
return "https://one-feel-config-images-bucket.oss-cn-chengdu.aliyuncs.com/" + clientType + "/"
|
return "https://oss.nianxx.cn/mp/static/" + clientType + "/";
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user