Browse Source

新增:产品购买页面及下单页面

master
科技小王子 7 months ago
parent
commit
6d403f1611
  1. 4
      api/oa/product/model/index.ts
  2. 10
      api/shop/goodsCoupon/model/index.ts
  3. 1
      components/AppHeader.vue
  4. 4
      nuxt.config.ts
  5. 219
      pages/product/checkout/index.vue
  6. 7
      pages/product/components/CardList.vue
  7. 93
      pages/product/create/components/PageBanner.vue
  8. 245
      pages/product/create/index.vue
  9. 25
      pages/product/createWebsite/index.vue
  10. 25
      pages/product/createWebsite/index2.vue
  11. 4
      utils/common.ts

4
api/oa/product/model/index.ts

@ -18,8 +18,12 @@ export interface Product {
content?: string;
// 父级分类ID
parentId?: number;
// 父级栏目名称
parentName?: string;
// 产品分类ID
categoryId?: number;
// 产品分类名称
categoryName?: string;
// 产品规格 0单规格 1多规格
specs?: number;
// 货架

10
api/shop/goodsCoupon/model/index.ts

@ -4,14 +4,14 @@ import type { PageParam } from '@/api';
*
*/
export interface GoodsCoupon {
//
id?: number;
//
id?: undefined,
// 商品id
goodsId?: number;
goodsId?: undefined,
// 优惠劵id
issueCouponId?: number;
issueCouponId?: undefined,
// 排序(数字越小越靠前)
sortNumber?: number;
sortNumber?: undefined,
// 状态, 0正常, 1冻结
status?: number;
// 是否删除, 0否, 1是

1
components/AppHeader.vue

@ -189,6 +189,7 @@ const reload = async () => {
sysDomain.value = company.value?.data?.domain;
localStorage.setItem('SysDomain', `${company.value?.data?.domain}`);
}
}
}

4
nuxt.config.ts

@ -33,10 +33,10 @@ export default defineNuxtConfig({
public: {
// 开发环境配置
// tenantId: '5',
apiServer: 'http://127.0.0.1:30000/api',
// apiServer: 'http://127.0.0.1:30000/api',
// 生产环境
// apiServer: 'https://common-api.websoft.top/api',
apiServer: 'https://common-api.websoft.top/api',
globalTitle: '网宿软件',
domain: 'websoft.top'
},

219
pages/product/checkout/index.vue

@ -0,0 +1,219 @@
<template>
<div class="lg:w-screen-xl w-full m-auto">
<Breadcrumb title="订单确认"/>
</div>
<div class="page-main md:w-screen-xl m-auto p-3">
<el-row :gutter="24">
<el-col :span="16" :xs="24">
<el-card shadow="hover" class="mb-4">
<template #header>
<div class="card-header font-bold">
<span>订单确认</span>
</div>
</template>
<el-descriptions title="云·企业官网(SaaS交付)" :column="1" class="mb-4">
<el-descriptions-item label="套餐版本:">标准版需备案</el-descriptions-item>
<el-descriptions-item label="购买时长:">1</el-descriptions-item>
</el-descriptions>
<el-descriptions title="设计服务" :column="1" class="mb-4">
<el-descriptions-item label="是否需要设计:">需要</el-descriptions-item>
<el-descriptions-item label="套餐版本:">标准版</el-descriptions-item>
</el-descriptions>
<el-descriptions title="合计:" :column="1" class="mb-4">
<el-descriptions-item label="总价格:">3000.00</el-descriptions-item>
<el-descriptions-item label="优惠价格:">1280.00</el-descriptions-item>
</el-descriptions>
</el-card>
<el-card shadow="hover" class="mb-4">
<template #header>
<div class="card-header font-bold">
<span>服务协议</span>
</div>
</template>
<div class="flex items-center">
<el-checkbox v-model="isAgree"></el-checkbox>
<span class="ml-1">我已阅读并同意</span>
<span class="text-blue-400 hover:text-blue-500 cursor-pointer" @click="openSpmUrl(`/article/374`, {}, 0, true)">计算机软件著作权登记服务纸质登记专属条款</span>
</div>
</el-card>
</el-col>
<el-col :span="8" :xs="24">
<el-card shadow="hover" class="mb-4">
<template #header>
<div class="card-header font-bold">
<span>扫码支付</span>
</div>
</template>
<div class="flex justify-center">
<el-radio-group v-model="form.code">
<el-radio-button value="1" border>微信支付</el-radio-button>
<el-radio-button value="12" border>支付宝</el-radio-button>
<el-radio-button value="24" border>余额支付</el-radio-button>
</el-radio-group>
</div>
<div class="flex justify-center py-4">
<el-avatar :size="250" src="https://oss.wsdns.cn/20240409/247a492abda94b08ace33fa5405628ca.jpeg"
shape="square" />
</div>
<el-form-item>
<el-button type="danger" :disabled="!isAgree" class="w-full" size="large" @click="onSubmit">去支付</el-button>
</el-form-item>
</el-card>
</el-col>
</el-row>
</div>
<!-- <div class="login-layout mt-[100px] m-auto sm:w-screen-xl w-full">-->
<!-- <div class="mt-[100px] m-auto flex sm:flex-row flex-col sm:p-0 p-3">-->
<!-- <div class="flash bg-white rounded-lg px-7 py-4 w-full">-->
<!-- <el-tabs class="flash bg-white ml-0">-->
<!-- <el-tab-pane label="个人开发者">-->
<!-- <el-form :model="form" label-width="auto" size="large" label-position="top" class="sm:w-screen-md w-full sm:py-2">-->
<!-- <el-form-item label="商品类型">-->
<!-- <el-input v-model="form.title" placeholder="请输入真实姓名" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="资源包类型">-->
<!-- <el-input v-model="form.productId" placeholder="请输入证件号码" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="身份证(正面)">-->
<!-- <Upload />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="身份证(反面)">-->
<!-- <Upload />-->
<!-- </el-form-item>-->
<!-- <el-form-item>-->
<!-- <el-button type="primary" size="large" @click="onSubmit">提交</el-button>-->
<!-- </el-form-item>-->
<!-- </el-form>-->
<!-- </el-tab-pane>-->
<!-- </el-tabs>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
</template>
<script setup lang="ts">
import {useConfigInfo, useToken, useWebsite} from "~/composables/configState";
import useFormData from '@/utils/use-form-data';
import type {User} from '@/api/system/user/model';
import {ref} from 'vue'
import {useServerRequest} from "~/composables/useServerRequest";
import type {ApiResult} from "~/api";
import type {Product} from "~/api/oa/product/model";
import Breadcrumb from "~/components/Breadcrumb.vue";
//
const runtimeConfig = useRuntimeConfig();
const route = useRoute();
const activeIndex = ref('');
const website = useWebsite()
const isAgree = ref<boolean>(false);
const config = useConfigInfo();
const token = useToken();
const userInfo = ref<User>();
//
const {form, assignFields} = useFormData<Product>({
// ID
productId: undefined,
// 0 1 2
type: undefined,
//
code: undefined,
//
title: undefined,
//
image: undefined,
//
content: undefined,
// ID
parentId: undefined,
// ID
categoryId: undefined,
// 0 1
specs: undefined,
//
position: undefined,
// ()
unitName: undefined,
//
price: undefined,
//
salePrice: undefined,
// (10 20)
deductStockType: undefined,
//
files: undefined,
//
sales: undefined,
//
stock: undefined,
//
gainIntegral: undefined,
//
recommend: undefined,
// ID
merchantId: undefined,
// 01
isShow: undefined,
// , 0 1 2 3
status: undefined,
//
comments: undefined,
//
sortNumber: undefined,
// ID
userId: undefined,
// , 0, 1
deleted: undefined,
// id
tenantId: undefined,
//
createTime: undefined,
//
updateTime: undefined,
});
const handleChange = (e) => {
console.log(e)
}
const onSubmit = async () => {
const {data: modify} = await useServerRequest<ApiResult<User>>('/auth/user', {
baseURL: runtimeConfig.public.apiServer,
method: 'put',
body: form
})
if (modify.value?.code == 0) {
ElMessage.success('修改成功')
}
}
const reload = async () => {
const {data: response} = await useServerRequest<ApiResult<Product>>(`/cms/cms-product/${getIdBySpm(5)}`, {baseURL: runtimeConfig.public.apiServer})
if (response.value?.data) {
assignFields(response.value?.data);
form.categoryName = '立即开通'
useHead({
title: `${form.title}`,
meta: [{name: website.value.keywords, content: website.value.comments}]
});
}
}
watch(
() => route.path,
(path) => {
activeIndex.value = path;
console.log(path, '=>Path')
reload();
},
{immediate: true}
);
</script>
<style lang="scss">
.text-a123 {
color: #f0f2f5;
}
</style>

7
pages/product/components/CardList.vue

@ -3,7 +3,7 @@
<el-row :gutter="24" class="flex">
<template v-for="(item,index) in list" :key="index">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb-5 min-w-xs">
<el-card shadow="hover" :body-style="{ padding: '0px' }" class="hover:bg-gray-50 cursor-pointer">
<el-card shadow="hover" :body-style="{ padding: '0px' }" class="hover:bg-gray-50 cursor-pointer" @click="openSpmUrl(`/item`, item, item.productId,true)">
<el-image :src="`${item.image}`" fit="contain" :lazy="true" class="w-full md:h-[150px] h-[199px] cursor-pointer" />
<div class="flex-1 px-4 py-5 sm:p-6 !p-4">
<div class="text-gray-700 dark:text-white text-base font-semibold flex flex-col gap-1.5">
@ -14,9 +14,8 @@
<div class="text-gray-500">{{ item.comments }}</div>
</div>
<div class="button-group flex justify-center mt-3">
<el-button class="w-full" size="large" :icon="ElIconView" @click="openSpmUrl(`/item`, item, item.productId,true)">查看详情</el-button>
<el-button type="primary" size="large" v-if="item.price && item.price > 0" class="w-full" :icon="ElIconShoppingCart">购买</el-button>
<el-button v-else class="w-full" size="large" :icon="ElIconShoppingCart">下载</el-button>
<el-button type="primary" class="w-full" size="large" :icon="ElIconView" @click.stop="openSpmUrl(`/product/create`,item,item.productId,true)">立即开通</el-button>
<el-button size="large" class="w-full" @click.stop="openSpmUrl(`https://10241.websoft.top/system/user`,item, item.productId,true)">产品控制台</el-button>
</div>
</div>
</el-card>

93
pages/product/create/components/PageBanner.vue

@ -0,0 +1,93 @@
<template>
<div class="banner m-auto relative sm:flex">
<svg viewBox="0 0 1440 181" fill="none" xmlns="http://www.w3.org/2000/svg"
class="pointer-events-none absolute w-full top-[-2px] transition-all text-green-5 flex-shrink-0 opacity-100 duration-[400ms] opacity-80 -z-10">
<mask id="path-1-inside-1_414_5526" fill="white">
<path d="M0 0H1440V181H0V0Z"></path>
</mask>
<path d="M0 0H1440V181H0V0Z" fill="url(#paint0_linear_414_5526)" fill-opacity="0.22"></path>
<path d="M0 2H1440V-2H0V2Z" fill="url(#paint1_linear_414_5526)" mask="url(#path-1-inside-1_414_5526)"></path>
<defs>
<linearGradient id="paint0_linear_414_5526" x1="720" y1="0" x2="720" y2="181" gradientUnits="userSpaceOnUse">
<stop stop-color="currentColor"></stop>
<stop offset="1" stop-color="currentColor" stop-opacity="0"></stop>
</linearGradient>
<linearGradient id="paint1_linear_414_5526" x1="0" y1="90.5" x2="1440" y2="90.5" gradientUnits="userSpaceOnUse">
<stop stop-color="currentColor" stop-opacity="0"></stop>
<stop offset="0.395" stop-color="currentColor"></stop>
<stop offset="1" stop-color="currentColor" stop-opacity="0"></stop>
</linearGradient>
</defs>
</svg>
<div class="md:w-screen-xl m-auto px-3">
<Breadcrumb :data="form" />
<div class="md:py-8 sm:py-16 md:px-0 px-4 py-8" _path="/templates" _dir="" _draft="false" _partial="false"
_locale=""
_id="content:4.templates.yml" _type="yaml" _source="content" _file="4.templates.yml" _stem="4.templates"
_extension="yml">
<div class="gap-8 sm:gap-y-16 lg:items-center" v-if="form">
<div class="w-full">
<h1
class="text-2xl font-bold tracking-tight text-gray-900 dark:text-white sm:text-3xl lg:text-4xl">
<span v-if="form.title">{{ form.title }}</span>
</h1>
<div class="mt-4 text-lg text-gray-500 dark:text-gray-400">
{{ form?.comments }}
</div>
<el-space class="mt-4">
<el-button
:icon="ElIconView"
@click="openSpmUrl(``)"
>
产品介绍
</el-button>
<el-button
:icon="ElIconView"
@click="openSpmUrl(``)"
>
客户案例
</el-button>
<el-button
:icon="ElIconView"
@click="openSpmUrl(``)"
>
网站模版
</el-button>
<el-button
:icon="ElIconMemo"
@click="openSpmUrl(``)"
>
产品文档
</el-button>
</el-space>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import {openSpmUrl} from "~/utils/common";
import Breadcrumb from "~/components/Breadcrumb.vue";
import type {Article} from "~/api/cms/article/model";
withDefaults(
defineProps<{
title?: string;
desc?: string;
buyUrl?: string;
form?: Article;
}>(),
{
title: 'Templates',
desc: 'Explore community templates to get up and running in a few seconds.',
demoUrl: '/product/website',
buyUrl: 'https://github.com/websoft9/ansible-templates'
}
);
</script>

245
pages/product/create/index.vue

@ -0,0 +1,245 @@
<template>
<PageBanner :form="form" title="订单确认"/>
<div class="page-main md:w-screen-xl m-auto p-3">
<el-row :gutter="24">
<el-col :span="16" :xs="24">
<el-form :model="form" label-width="auto" label-position="left" class="w-full">
<el-card shadow="hover" class="mb-4">
<template #header>
<div class="card-header font-bold">
<span>·企业官网SaaS交付</span>
</div>
</template>
<div class="flex flex-col">
<el-form-item label="购买个数">
<el-input-number v-model="form.specs" :min="1" :max="10" @change="handleChange" />
</el-form-item>
<el-form-item label="购买时长">
<el-radio-group v-model="form.code">
<el-radio-button value="1" border>1个月</el-radio-button>
<el-radio-button value="12" border>1</el-radio-button>
<el-radio-button value="24" border>2</el-radio-button>
<el-radio-button value="36" border>3</el-radio-button>
<el-radio-button value="60" border>5</el-radio-button>
<el-radio-button value="120" border>10</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="套餐版本">
<el-radio-group v-model="form.image">
<el-radio-button value="1" border>标准版需备案</el-radio-button>
<el-radio-button value="2" border>标准版香港节点适合全球访问不支持备案</el-radio-button>
</el-radio-group>
</el-form-item>
</div>
</el-card>
<el-card shadow="hover" class="mb-4">
<template #header>
<div class="card-header font-bold">
<span>设计服务</span>
</div>
</template>
<div class="flex flex-col">
<el-form-item label="是否需要设计服务">
<el-radio-group v-model="form.code">
<el-radio-button value="1" border>需要</el-radio-button>
<el-radio-button value="12" border>不需要</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="套餐版本">
<el-radio-group v-model="form.image">
<el-radio-button value="1" border>需要备案</el-radio-button>
<el-radio-button value="2" border>不需要备案</el-radio-button>
</el-radio-group>
</el-form-item>
</div>
</el-card>
<!-- <el-form-item label="证件号码">-->
<!-- <el-input v-model="form.idCard" placeholder="请输入证件号码" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="身份证(正面)">-->
<!-- <Upload />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="身份证(反面)">-->
<!-- <Upload />-->
<!-- </el-form-item>-->
</el-form>
</el-col>
<el-col :span="8" :xs="24">
<el-card shadow="hover" class="mb-4">
<template #header>
<div class="card-header font-bold">
<span>配置清单</span>
</div>
</template>
<el-descriptions title="云·企业官网(SaaS交付)" :column="1" class="mb-4">
<el-descriptions-item label="套餐版本:">标准版需备案</el-descriptions-item>
<el-descriptions-item label="购买时长:">1</el-descriptions-item>
</el-descriptions>
<el-descriptions title="设计服务" :column="1" class="mb-4">
<el-descriptions-item label="是否需要设计:">需要</el-descriptions-item>
<el-descriptions-item label="套餐版本:">标准版</el-descriptions-item>
</el-descriptions>
<el-descriptions title="合计:" :column="1" class="mb-4">
<el-descriptions-item label="总价格:">3000.00</el-descriptions-item>
<el-descriptions-item label="优惠价格:">1280.00</el-descriptions-item>
</el-descriptions>
<el-form-item>
<el-button type="danger" class="w-full" size="large" @click="openSpmUrl(`/product/checkout`)">确认订单</el-button>
</el-form-item>
</el-card>
</el-col>
</el-row>
</div>
<!-- <div class="login-layout mt-[100px] m-auto sm:w-screen-xl w-full">-->
<!-- <div class="mt-[100px] m-auto flex sm:flex-row flex-col sm:p-0 p-3">-->
<!-- <div class="flash bg-white rounded-lg px-7 py-4 w-full">-->
<!-- <el-tabs class="flash bg-white ml-0">-->
<!-- <el-tab-pane label="个人开发者">-->
<!-- <el-form :model="form" label-width="auto" size="large" label-position="top" class="sm:w-screen-md w-full sm:py-2">-->
<!-- <el-form-item label="商品类型">-->
<!-- <el-input v-model="form.title" placeholder="请输入真实姓名" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="资源包类型">-->
<!-- <el-input v-model="form.productId" placeholder="请输入证件号码" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="身份证(正面)">-->
<!-- <Upload />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="身份证(反面)">-->
<!-- <Upload />-->
<!-- </el-form-item>-->
<!-- <el-form-item>-->
<!-- <el-button type="primary" size="large" @click="onSubmit">提交</el-button>-->
<!-- </el-form-item>-->
<!-- </el-form>-->
<!-- </el-tab-pane>-->
<!-- </el-tabs>-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
</template>
<script setup lang="ts">
import {useConfigInfo, useToken, useWebsite} from "~/composables/configState";
import useFormData from '@/utils/use-form-data';
import type {User} from '@/api/system/user/model';
import {ref} from 'vue'
import {useServerRequest} from "~/composables/useServerRequest";
import type {ApiResult} from "~/api";
import type {Product} from "~/api/oa/product/model";
import PageBanner from './components/PageBanner.vue';
//
const runtimeConfig = useRuntimeConfig();
const route = useRoute();
const activeIndex = ref('');
const website = useWebsite()
const config = useConfigInfo();
const token = useToken();
const userInfo = ref<User>();
//
const {form, assignFields} = useFormData<Product>({
// ID
productId: undefined,
// 0 1 2
type: undefined,
//
code: undefined,
//
title: undefined,
//
image: undefined,
//
content: undefined,
// ID
parentId: undefined,
// ID
categoryId: undefined,
// 0 1
specs: undefined,
//
position: undefined,
// ()
unitName: undefined,
//
price: undefined,
//
salePrice: undefined,
// (10 20)
deductStockType: undefined,
//
files: undefined,
//
sales: undefined,
//
stock: undefined,
//
gainIntegral: undefined,
//
recommend: undefined,
// ID
merchantId: undefined,
// 01
isShow: undefined,
// , 0 1 2 3
status: undefined,
//
comments: undefined,
//
sortNumber: undefined,
// ID
userId: undefined,
// , 0, 1
deleted: undefined,
// id
tenantId: undefined,
//
createTime: undefined,
//
updateTime: undefined,
});
const handleChange = (e) => {
console.log(e)
}
const onSubmit = async () => {
const {data: modify} = await useServerRequest<ApiResult<User>>('/auth/user', {
baseURL: runtimeConfig.public.apiServer,
method: 'put',
body: form
})
if (modify.value?.code == 0) {
ElMessage.success('修改成功')
}
}
const reload = async () => {
const {data: response} = await useServerRequest<ApiResult<Product>>(`/cms/cms-product/${getIdBySpm(5)}`, {baseURL: runtimeConfig.public.apiServer})
if (response.value?.data) {
assignFields(response.value?.data);
form.categoryName = '立即开通'
useHead({
title: `${form.title}`,
meta: [{name: website.value.keywords, content: website.value.comments}]
});
}
}
watch(
() => route.path,
(path) => {
activeIndex.value = path;
console.log(path, '=>Path')
reload();
},
{immediate: true}
);
</script>
<style lang="scss">
.text-a123{
color: #f0f2f5;
}
</style>

25
pages/product/createWebsite/index.vue

@ -0,0 +1,25 @@
<template>
</template>
<script setup lang="ts">
//
import {useServerRequest} from "~/composables/useServerRequest";
import type {ApiResult} from "~/api";
import type {Company} from "~/api/system/company/model";
const {data: website} = await useServerRequest<ApiResult<Company>>('/cms/website/createWebsite', {
baseURL: 'http://127.0.0.1:9002/api',
method: 'post',
body: company.value?.data
})
if (website.value?.code == 401) {
console.log('网站不存在', website.value)
}
if (website.value?.code == 0) {
console.log('网站存在', website.value)
}
</script>
<style scoped lang="less">
</style>

25
pages/product/createWebsite/index2.vue

@ -0,0 +1,25 @@
<template>
</template>
<script setup lang="ts">
//
import {useServerRequest} from "~/composables/useServerRequest";
import type {ApiResult} from "~/api";
import type {Company} from "~/api/system/company/model";
const {data: website} = await useServerRequest<ApiResult<Company>>('/cms/website/createWebsite', {
baseURL: 'http://127.0.0.1:9002/api',
method: 'post',
body: company.value?.data
})
if (website.value?.code == 401) {
console.log('网站不存在', website.value)
}
if (website.value?.code == 0) {
console.log('网站存在', website.value)
}
</script>
<style scoped lang="less">
</style>

4
utils/common.ts

@ -107,11 +107,11 @@ export function openSpmUrl(path: string, d?: any, id = 0, isOpen?: boolean, isTo
const config = useWebsite();
const spm = ref<string>('');
const model = ref<string>('c');
const tid = config.value.tenantId || 0;
const tid = localStorage.getItem('TID_ADMIN') || 0;
const mid = config.value.loginUser?.merchantId || 0;
const pid = d?.parentId || 0;
const cid = d?.categoryId || 0;
const uid = config.value.loginUser?.userId || 0;
const uid = localStorage.getItem('UserId') || 0;
const timestamp = ref(Date.now() / 1000);
let token = uuidv4();

Loading…
Cancel
Save