From 52f60fcfc348ad26185c22a074b8551429ac5149 Mon Sep 17 00:00:00 2001
From: peng <peng.com>
Date: 星期六, 11 十月 2025 16:31:16 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/send_coupon' into send_coupon
---
manager/src/views/store-tag/store-tag.vue | 272 ++++++++++++
seller/src/views/store-coupon/coupon_store.vue | 11
seller/src/views/template/goodsCustomizeTemplate.vue | 790 +++++++++++++++++++++++++++++++++++
manager/src/api/store-tag.js | 66 +++
manager/src/views/seller/shop/shopDetail.vue | 115 +++++
seller/src/api/goods-customeize-template.js | 47 ++
6 files changed, 1,287 insertions(+), 14 deletions(-)
diff --git a/manager/src/api/store-tag.js b/manager/src/api/store-tag.js
new file mode 100644
index 0000000..c709585
--- /dev/null
+++ b/manager/src/api/store-tag.js
@@ -0,0 +1,66 @@
+import service from "@/libs/axios";
+
+
+export const getPageList = (data) =>{
+ return service({
+ url: "/lmk/store-tag/page",
+ method: "GET",
+ params: data
+ })
+}
+export const getTag = (data) =>{
+ return service({
+ url: "/lmk/store-tag/list",
+ method: "GET",
+ params: data
+ })
+}
+export const addStoreTag =(data) =>{
+ return service({
+ url: "/lmk/store-tag",
+ method: "POST",
+ data: data
+ })
+}
+export const bind =(data) =>{
+ return service({
+ url: "/lmk/store-tag/bind",
+ method: "POST",
+ data: data
+ })
+}
+export const editTag = (data)=>{
+ return service({
+ url: "/lmk/store-tag",
+ method: "PUT",
+ data: data
+ })
+}
+
+export const delTag = (data)=>{
+ return service({
+ url: "/lmk/store-tag/" + data,
+ method: "DELETE",
+ })
+}
+export const removeBatch = (data) =>{
+ return service({
+ url: "/lmk/store-tag/batch",
+ method: "DELETE",
+ data:data
+ })
+}
+
+export const getStoreTagsById =(data) =>{
+ return service({
+ url: "/lmk/store-tag/storeTags/" + data,
+ method: "GET",
+ })
+}
+
+export const delTagByStoreTagRefId = (data)=>{
+ return service({
+ url: "/lmk/store-tag/delTagByStoreTagRefId/" + data,
+ method: "DELETE",
+ })
+}
diff --git a/manager/src/views/seller/shop/shopDetail.vue b/manager/src/views/seller/shop/shopDetail.vue
index c6bccdb..952b59f 100644
--- a/manager/src/views/seller/shop/shopDetail.vue
+++ b/manager/src/views/seller/shop/shopDetail.vue
@@ -121,6 +121,29 @@
</span>
</p>
<p class="item">
+ <span class="label">搴楅摵鏍囩锛�</span>
+ <span class="info">
+ <template v-if="tagList?.length > 0">
+ <!-- 閬嶅巻鏍囩鍒楄〃 -->
+ <span v-for="(tag, index) in tagList" :key="tag.id">
+ {{ tag.tagName }}
+ <button
+ style="width: 20px; height: 20px; line-height: 1; border: none; background: #f0f0f0; border-radius: 50%; cursor: pointer; margin-left: 4px; font-size: 12px; display: inline-flex; align-items: center; justify-content: center;"
+ @click.stop="handleDeleteTag(tag.id, index)"
+ title="鍒犻櫎鏍囩"
+ >
+ 脳
+ </button>
+ <template v-if="index !== tagList.length - 1">銆�</template>
+ </span>
+ </template>
+ <template v-else>鏆傛棤鏍囩</template>
+ </span>
+ </p>
+ <div style="display: flex;align-items: center;justify-content: center;">
+ <Button type="primary" @click="addStoreTag(storeInfo)">鏂板鏍囩</Button>
+ </div>
+ <p class="item">
<span class="label">搴楅摵绠�浠嬶細</span>
<span class="info">
{{storeInfo.storeDesc?storeInfo.storeDesc:'鏆傛湭瀹屽杽'}}
@@ -559,6 +582,22 @@
</Row>
</div>
</TabPane>
+
+ <Modal
+ v-model="showModal"
+ title="鏂板鏍囩"
+ width="800"
+ :mask-closable="false"
+ >
+ <Select v-model="tagForm.storeTagId" placeholder="璇烽�夋嫨" @on-query-change="searchChange" filterable
+ clearable style="width: 150px">
+ <Option v-for="item in tagOptions" :value="item.id" :key="item.id">{{ item.tagName }}</Option>
+ </Select>
+ <div slot="footer">
+ <Button @click="showModal = false">鍙栨秷</Button>
+ <Button type="primary" @click="handleSubmit" :loading="submitLoading">纭畾</Button>
+ </div>
+ </Modal>
</Tabs>
</Card>
@@ -566,7 +605,7 @@
</template>
<script>
-
+ import { getTag,bind,getStoreTagsById,delTagByStoreTagRefId } from "@/api/store-tag"
import ossManage from "@/views/sys/oss-manage/ossManage";
import * as RegExp from '@/libs/RegExp.js';
import {getCategoryTree} from "@/api/goods";
@@ -577,15 +616,23 @@
export default {
name: "member",
components: {
-
ossManage,
},
data() {
return {
+ tagOptions:[],
+ submitLoading:false,
+ tagForm:{
+ storeId:null,
+ storeTagId:"",
+ },
+ showModal:false,
id: "",//搴楅摵id
categories: [], //搴楅摵闈欓煶鑼冨洿
loading: true, // 琛ㄥ崟鍔犺浇鐘舵��
- storeInfo: {},//搴楅摵淇℃伅
+ storeInfo: {
+ },//搴楅摵淇℃伅
+ tagList:[],
checkAllGroup: [], //閫変腑鐨勭粡钀ュ垎绫�
selectDate: null, // 鐢宠鏃堕棿
@@ -846,7 +893,69 @@
};
},
methods: {
+ handleDeleteTag(storeTagRefId){
+ console.log(storeTagRefId)
+ delTagByStoreTagRefId(storeTagRefId).then(res=>{
+ if (res.code === 200){
+ this.$Message.success("鍒犻櫎鎴愬姛")
+ }
+ this.getStoreTags();
+ })
+
+ },
+
+ getStoreTags(){
+ getStoreTagsById(this.id).then(res =>{
+ if (res.code === 200){
+ this.$set(this, "tagList", res.data);
+ }
+ })
+
+ },
+
+ searchChange(val){
+ this.getStoreTag(val)
+ },
+ getStoreTag(val){
+ const params = {
+ tagName: ''
+ }
+ if (val) {
+ params.tagName = val;
+ } else {
+ params.tagName = ''
+ }
+ getTag(params).then(res =>{
+ if (res.code ===200){
+ this.tagOptions = res.data
+ }
+ })
+ },
+ handleSubmit(){
+ if (this.tagForm.storeTagId === null || this.tagForm.storeTagId ===""){
+ this.$Message.error("璇烽�夋嫨鏍囩")
+ return
+ }
+ this.showModal = false;
+ bind(this.tagForm).then(res =>{
+ if (res.code === 200){
+
+ }
+ this.getStoreTags();
+ this.getStoreTag();
+ })
+
+ },
+ addStoreTag(info){
+ console.log(info)
+ this.tagForm.storeId = info.storeId;
+ this.tagForm.storeTagId = "";
+ this.showModal = true;
+ },
init() {
+ this.getStoreTags();
+
+ this.getStoreTag();
//鏌ュ簵閾哄熀鏈俊鎭�
this.getStoreInfo();
//鏌ヨ搴楅摵鍒嗙被
diff --git a/manager/src/views/store-tag/store-tag.vue b/manager/src/views/store-tag/store-tag.vue
new file mode 100644
index 0000000..14ae529
--- /dev/null
+++ b/manager/src/views/store-tag/store-tag.vue
@@ -0,0 +1,272 @@
+<template>
+ <div>
+ <card>
+ <Form
+ ref="searchForm"
+ @keydown.enter.native="handleSearch"
+ :model="searchForm"
+ inline
+ :label-width="70"
+ class="search-form"
+ >
+ <Form-item label="鏍囩鍚嶇О" prop="tagName">
+ <Input
+ type="text"
+ v-model="searchForm.tagName"
+ clearable
+ @on-clear="handleSearch"
+ @on-change="handleSearch"
+ style="width: 160px"
+ />
+ </Form-item>
+ <Button
+ @click="handleSearch"
+ type="primary"
+ icon="ios-search"
+ class="search-btn"
+ >鎼滅储</Button
+ >
+ </Form>
+ <Row class="operation padding-row">
+ <Button @click="openAdd" type="info">娣诲姞</Button>
+ <Button @click="delBatch" type="error">鎵归噺鍒犻櫎</Button>
+ </Row>
+ <Table
+ :loading="loading"
+ border
+ :columns="columns"
+ :data="tagList"
+ ref="table"
+ sortable="custom"
+ @on-sort-change="changeSort"
+ @on-selection-change="showSelect"
+ >
+ <template slot-scope="{ row, index }" slot="action">
+ <Button type="info" size="small" style="margin-right: 5px" @click="openEdit(row)">缂栬緫鏍囩</Button>
+ <Button type="error" size="small" style="margin-right: 5px" @click="del(row)">鍒犻櫎鏍囩</Button>
+ </template>
+ </Table>
+
+ <Row type="flex" justify="end" class="mt_10">
+ <Page
+ :current="searchForm.pageNumber"
+ :total="total"
+ :page-size="searchForm.pageSize"
+ @on-change="changePage"
+ @on-page-size-change="changePageSize"
+ :page-size-opts="[10, 20, 50]"
+ size="small"
+ show-total
+ show-elevator
+ show-sizer
+ ></Page>
+ </Row>
+
+ <Modal
+ v-model="modelShow"
+ :title="modelTitle"
+ >
+ <Form ref="form" :model="form" :label-width="70" :rules="rules">
+ <FormItem label="鏍囩鍚嶇О" prop="tagName">
+ <Input v-model="form.tagName" autocomplete="off"/>
+ </FormItem>
+ </Form>
+ <div slot="footer">
+ <Button type="text" @click="modelClose">鍙栨秷</Button>
+ <Button type="primary" :loading="submitLoading" @click="saveOrUpdate">鎻愪氦</Button>
+ </div>
+ </Modal>
+ </card>
+ </div>
+</template>
+<script>
+import { getPageList,addStoreTag,editTag,delTag,removeBatch } from "@/api/store-tag"
+ export default {
+ name: "store-tag",
+ data(){
+ return{
+ loading:false,
+ columns:[
+ {
+ type: 'selection',
+ width: 60,
+ align: 'center'
+ },
+ {
+ title:'鏍囩鍚嶇О',
+ key: 'tagName',
+ minWidth: 60,
+ tooltip: true,
+ },
+ {
+ title: '鎿嶄綔',
+ key: 'action',
+ slot: 'action',
+ minWidth: 150,
+ align: 'center'
+ }
+ ],
+ total:0,
+ tagList:[],
+ searchForm: {
+ // 鎼滅储妗嗗垵濮嬪寲瀵硅薄
+ pageNumber: 1, // 褰撳墠椤垫暟
+ pageSize: 10, // 椤甸潰澶у皬
+ tagName: '', // 鏍囩鍚嶇О
+ },
+ // 瀵硅瘽妗嗘爣棰�
+ modelTitle:'',
+ modelShow:false,
+ submitLoading:false,
+ // 琛ㄥ崟
+ form: {
+ id: '',
+ tagName: '',
+ },
+ rules: {
+ tagName: [
+ {required: true, message: "鏍囩鍚嶇О涓嶈兘涓虹┖", trigger: "blur"}
+ ],
+ },
+ //澶氶��
+ selectCount: 0, // 宸查�夋暟閲�
+ selectList: [], // 宸查�夋暟鎹垪琛�
+ }
+
+ },
+ mounted(){
+ this.init();
+ },
+ methods:{
+ init(){
+ this.getTagList()
+ },
+ openAdd(){
+ this.modelTitle = "鏂板鏍囩";
+ this.modelShow = true;
+ this.form={
+ id: '',
+ tagName: '',
+ }
+ },
+ openEdit(row){
+ this.form.id = row.id;
+ this.form.tagName = row.tagName;
+ this.modelTitle= "淇敼鏍囩";
+ this.modelShow = true;
+ },
+ saveOrUpdate() {
+ this.$refs.form.validate(valid => {
+ if (valid) {
+ this.submitLoading = true
+ if (this.form.id) {
+ // 淇敼
+ editTag(this.form).then(res => {
+ if (res.code === 200) {
+ this.$Message.success("淇敼鎴愬姛");
+ this.modelClose()
+ this.getTagList()
+ }
+ })
+ } else {
+ // 鏂板
+ addStoreTag(this.form).then(res => {
+ if (res.code === 200) {
+ this.$Message.success("娣诲姞鎴愬姛");
+ this.modelClose()
+ this.getTagList()
+ }
+ })
+ }
+ }
+ });
+ },
+ del(row){
+ delTag(row.id).then(res =>{
+ if (res.code === 200){
+ this.$Message.success("鍒犻櫎鎴愬姛")
+ }
+ this.getTagList();
+ })
+ },
+ delBatch() {
+ if (this.selectCount <= 0) {
+ this.$Message.warning("鎮ㄨ繕鏈�夋嫨瑕佸垹闄ょ殑鏁版嵁");
+ return;
+ }
+
+ // 鏄剧ず纭瀵硅瘽妗�
+ this.$Modal.confirm({
+ title: '纭鍒犻櫎',
+ content: `鎮ㄧ‘瀹氳鍒犻櫎閫変腑鐨� ${this.selectCount} 鏉℃暟鎹悧锛焋,
+ onOk: () => {
+ // 鐢ㄦ埛鐐瑰嚮纭鍚庢墽琛屽垹闄�
+ this.removeBatch();
+ },
+ onCancel: () => {
+ this.$Message.info('宸插彇娑堝垹闄�');
+ }
+ });
+ },
+
+ async removeBatch() {
+ try {
+ const res = await removeBatch(this.selectList);
+ if (res.code === 200) {
+ this.getTagList();
+ this.selectedRows = [];
+ this.selectCount = 0;
+ this.$Message.success('鍒犻櫎鎴愬姛');
+ } else {
+ this.$Message.error(res.message || '鍒犻櫎澶辫触');
+ }
+ } catch (err) {
+ console.log(err);
+ this.$Message.error('璇锋眰澶辫触锛岃閲嶈瘯');
+ }
+ },
+ // 鍏抽棴寮圭獥
+ modelClose() {
+ this.submitLoading = false
+ this.modelShow = false
+ },
+ getTagList(){
+ this.loading = true;
+ getPageList(this.searchForm).then((res) => {
+ this.loading = false;
+ if (res.code === 200) {
+ this.tagList = res.data;
+ this.total = res.total;
+ }
+ });
+ this.loading = false;
+ },
+ handleSearch(){
+ this.searchForm.pageNumber = 1;
+ this.searchForm.pageSize = 10;
+ this.getTagList();
+ },
+ // 鍒嗛〉 鏀瑰彉椤电爜
+ changePage(v) {
+ this.searchForm.pageNumber = v;
+ this.getTagList();
+ },
+ // 鍒嗛〉 鏀瑰彉椤垫暟
+ changePageSize(v) {
+ this.searchForm.pageNumber = 1;
+ this.searchForm.pageSize = v;
+ this.getTagList();
+ },
+ changeSort(){
+
+ },
+ showSelect(e){
+ this.selectList = e.map(d => d.id);
+ this.selectCount = e.length;
+ },
+ },
+ }
+</script>
+<style scoped lang="scss">
+
+</style>
diff --git a/seller/src/api/goods-customeize-template.js b/seller/src/api/goods-customeize-template.js
new file mode 100644
index 0000000..2003aa8
--- /dev/null
+++ b/seller/src/api/goods-customeize-template.js
@@ -0,0 +1,47 @@
+import service from "../libs/axios";
+
+export const getPage = (params) =>{
+ return service({
+ url: "/lmk/goodsCustomizeTemplate",
+ method: "GET",
+ params: params
+ })
+}
+
+export const edit = (params) =>{
+ return service({
+ url: "/lmk/goodsCustomizeTemplate",
+ method: "PUT",
+ data: params
+ })
+}
+
+export const add = (params) =>{
+ return service({
+ url: "/lmk/goodsCustomizeTemplate",
+ method: "POST",
+ data: params
+ })
+}
+
+
+export const del = (params) =>{
+ return service({
+ url: "/lmk/goodsCustomizeTemplate/" +params,
+ method: "DELETE",
+ })
+}
+
+export const changeStatus = (params) =>{
+ return service({
+ url: "/lmk/goodsCustomizeTemplate/changeStatus/" +params,
+ method: "PUT",
+ })
+}
+
+export const detail = (params) =>{
+ return service({
+ url: "/lmk/goodsCustomizeTemplate/" +params,
+ method: "GET",
+ })
+}
diff --git a/seller/src/views/store-coupon/coupon_store.vue b/seller/src/views/store-coupon/coupon_store.vue
index 64862b6..3c7a21c 100644
--- a/seller/src/views/store-coupon/coupon_store.vue
+++ b/seller/src/views/store-coupon/coupon_store.vue
@@ -28,17 +28,6 @@
<Option value="GENERATE">鐢熸垚</Option>
</Select>
</FormItem>
- <FormItem label="鍚敤鐘舵��:">
- <Select
- v-model="listQuery.status"
- placeholder="鍏ㄩ儴鐘舵��"
- clearable
- style="width: 180px"
- >
- <Option value="ENABLE">鍚敤</Option>
- <Option value="DISABLE">绂佺敤</Option>
- </Select>
- </FormItem>
</Form>
</div>
</Card>
diff --git a/seller/src/views/template/goodsCustomizeTemplate.vue b/seller/src/views/template/goodsCustomizeTemplate.vue
new file mode 100644
index 0000000..7ad97b1
--- /dev/null
+++ b/seller/src/views/template/goodsCustomizeTemplate.vue
@@ -0,0 +1,790 @@
+<template>
+ <div class="coupon-management">
+ <!-- 鎼滅储鍖哄煙 -->
+ <Card class="filter-container">
+ <div class="filter-header">
+ <Icon type="ios-search" size="18" />
+ <span class="filter-title">绛涢�夋悳绱�</span>
+ <div class="filter-actions">
+ <Button type="primary" @click="getList" size="small">鏌ヨ鎼滅储</Button>
+ <Button @click="handleResetSearch" size="small" style="margin-left: 10px;">閲嶇疆</Button>
+ <Button type="primary" @click="addModal" size="small" style="margin-left: 10px;">鏂板</Button>
+ </div>
+ </div>
+ <div class="filter-content">
+ <Form
+ :model="listQuery"
+ :label-width="90"
+ class="search-form"
+ inline
+ >
+ <FormItem label="妯℃澘鍚嶇О">
+ <Input
+ v-model="listQuery.templateName"
+ style="width: 180px;"
+ clearable
+ placeholder="璇疯緭鍏ユā鏉垮悕绉�"
+ >
+ </Input>
+ </FormItem>
+ <FormItem label="鍚敤鐘舵��:">
+ <Select
+ v-model="listQuery.status"
+ placeholder="鍏ㄩ儴鐘舵��"
+ clearable
+ style="width: 180px"
+ >
+ <Option value="DISABLE">鏈惎鐢�</Option>
+ <Option value="ENABLE">宸茶捣鐢�</Option>
+ </Select>
+ </FormItem>
+
+
+ </Form>
+ </div>
+ </Card>
+
+ <!-- 琛ㄦ牸鍖哄煙 -->
+ <Card class="table-container">
+ <Table
+ :loading="listLoading"
+ border
+ :columns="tableColumns"
+ :data="list"
+ ref="table"
+ class="coupon-table"
+ >
+ <template slot-scope="{ row }" slot="action">
+ <Button
+ type="primary"
+ size="small"
+ style="margin-right: 5px"
+ @click="delTemplate(row)"
+ >鍒犻櫎</Button
+ >
+ <Button
+ type="primary"
+ size="small"
+ style="margin-right: 5px"
+ @click="updateTemplate(row)"
+ >淇敼</Button
+ >
+ <Button
+ type="primary"
+ size="small"
+ style="margin-right: 5px"
+ @click="changeStatus(row)"
+ >{{ row.status ==='ENABLE' ? '绂佺敤':'寮�鍚�'}}</Button
+ >
+ </template>
+ </Table>
+ </Card>
+
+ <!-- 鍒嗛〉鍖哄煙 -->
+ <div class="pagination-container">
+ <Page
+ :current="listQuery.pageNumber"
+ :page-size="listQuery.pageSize"
+ :total="total"
+ :page-size-opts="[10, 20, 30, 50]"
+ show-elevator
+ show-sizer
+ show-total
+ @on-change="handleCurrentChange"
+ @on-page-size-change="handleSizeChange"
+ />
+ </div>
+
+ <Modal
+ v-model="showModal"
+ :title="modalTitle"
+ width="800"
+ :mask-closable="false"
+ >
+ <Form
+ ref="form"
+ :model="form"
+ :label-width="90"
+ class="search-form"
+ :rules="formRules"
+ inline>
+ <Row>
+ <Col :span="24">
+ <FormItem label="妯℃澘鍚嶇О" prop="templateName">
+ <Input v-model="form.templateName" autocomplete="off"/>
+ </FormItem>
+ </Col>
+ <Col :span="24">
+ <FormItem label="閫夋嫨鏂板鏍囬">
+ <Button type="primary" @click="addTitle('TEXT')">娣诲姞鏂囧瓧鏍囬</Button>
+ <Button type="primary" style="margin-left: 10px" @click="addTitle('IMAGE')">娣诲姞鍥剧墖鏍囬</Button>
+ </FormItem>
+ </Col>
+
+ <Col :span="24">
+
+ <!-- 宸叉坊鍔犵殑鏍囬鍒楄〃 -->
+ <div v-for="(title, index) in form.titles" :key="index" class="title-item">
+ <card class="title-text">
+ <Input v-model="title.templateTitle" placeholder="璇疯緭鍏ユ枃鏈爣棰�" style="width: 300px; margin-top: 8px;"/>
+ <Button class="delete-btn" type="text" @click="removeTitle(index)" style="color: #ff4d4f;">鍒犻櫎</Button>
+ </card>
+<!-- <card v-if="title.contentType === 'IMAGE'" class="title-image">-->
+<!-- <Upload-->
+<!-- v-if="!title.imgTempUrl"-->
+<!-- :before-upload="(file) => handleBeforeUpload(file,title)"-->
+<!-- :format="['jpg','jpeg','png','gif']"-->
+<!-- :max-size="20480"-->
+<!-- action=""-->
+<!-- accept="image/*"-->
+<!-- >-->
+<!-- <Button icon="ios-cloud-upload-outline">涓婁紶灏侀潰鍥剧墖</Button>-->
+<!-- </Upload>-->
+<!-- <div v-else class="upload-file-info">-->
+
+<!-- <Col :span="24">-->
+<!-- <img :src="title.imgTempUrl" alt="娲诲姩鍥剧墖" class="preview-image-limit">-->
+<!-- </Col>-->
+<!-- <Button type="text" @click="handleRemoveImage(title)">鍒犻櫎</Button>-->
+<!-- </div>-->
+
+<!-- <Button class="delete-btn" type="text" @click="removeTitle(index)" style="color: #ff4d4f;">鍒犻櫎</Button>-->
+<!-- </card>-->
+ </div>
+ </Col>
+ <Col :span="24">
+ <FormItem label="妯℃澘鍥剧墖" >
+ <div style="display: flex; flex-wrap: wrap;">
+ <vuedraggable :animation="200" :list="showListImages">
+ <div v-for="(item, __index) in showListImages" :key="__index"
+ class="demo-upload-list">
+ <template>
+ <img :src="item"/>
+ <div class="demo-upload-list-cover">
+ <div>
+ <Icon size="30" type="md-search" @click.native="handleViewGoodsPicture(item)"></Icon>
+ <Icon size="30" type="md-trash" @click.native="handleRemoveGoodsPicture(item)"></Icon>
+ </div>
+ </div>
+ </template>
+ </div>
+ </vuedraggable>
+ </div>
+ <div style="width: 100%;display: flex;justify-content: start;margin-top: 10px;">
+ <Button @click="handleCLickImg('goodsGalleryFiles')" type="primary">涓婁紶鍥剧墖</Button>
+ </div>
+ <Modal v-model="goodsPictureVisible" title="View Image">
+ <img v-if="goodsPictureVisible" :src="previewGoodsPicture" style="width: 100%"/>
+ </Modal>
+ </FormItem>
+ </Col>
+
+ </Row>
+
+
+ </Form>
+ <div slot="footer">
+ <Button type="text" @click="showModal = false">鍏抽棴</Button>
+ <Button type="primary" :loading="submitLoading" @click="saveOrUpdate">纭</Button>
+ </div>
+ </Modal>
+
+ <Modal v-model="picModelFlag" width="1200px">
+ <div class="demo-upload-list" v-for="(item,index) in showListImages">
+ <template>
+ <img :src="item">
+ <div class="demo-upload-list-cover">
+ <Icon type="ios-eye-outline" @click.native="handleView(item)"></Icon>
+ <Icon type="ios-trash-outline" @click.native="handleRemove(null,index)"></Icon>
+ </div>
+ </template>
+ </div>
+ <div class="demo-upload-list">
+ <Upload
+ :before-upload="upLoadImg"
+ accept="image/*"
+ action="-"
+ type="drag"
+ style=" display: inline-block;width: 58px"
+ >
+ <div style="width: 58px;height:58px;line-height: 58px;">
+ <Icon type="ios-camera" size="20"></Icon>
+ </div>
+ </Upload>
+ </div>
+ </Modal>
+ <Modal v-model="visible" title="棰勮鍥剧墖">
+ <img v-if="visible" :src="previewPicture" style="width: 100%">
+ </Modal>
+
+ </div>
+</template>
+<script>
+
+import { getPage,edit,add,del,changeStatus,detail } from "@/api/goods-customeize-template.js"
+import vuedraggable from "vuedraggable";
+import COS from "cos-js-sdk-v5";
+import {getFileKey} from "@/utils/file.js";
+import {getFilePreview, getSts} from "@/api/file";
+
+export default {
+ name: 'GoodsCustomizeTemplate',
+ components: {vuedraggable},
+ data() {
+ return {
+ // 棰勮鍥剧墖璺緞
+ previewPicture: "",
+ visible:false,
+ picModelFlag: false, // 鍥剧墖閫夋嫨鍣�
+ goodsPictureVisible: false,
+ showListImages: [],
+ listImages: [],
+ previewGoodsPicture: "",
+ selectedFormBtnName: "", // 鐐瑰嚮鍥剧墖缁戝畾form
+
+ //鏂板
+ modalTitle:"",
+ showModal:false,
+
+ list: [],
+ total: 0,
+ listLoading: false,
+ submitLoading: false,
+
+ listQuery: {
+ pageNumber: 1,
+ pageSize: 10,
+ templateName:"",
+ status:"",
+ },
+ form:{
+ titles: []
+ },
+ // 琛ㄥ崟楠岃瘉瑙勫垯
+ formRules: {
+ templateName:[
+ {required:true,message:"妯℃澘鍚嶄笉鑳戒负绌�",trigger:"blur"}
+ ]
+ },
+
+ // 琛ㄥご閰嶇疆
+ tableColumns: [
+ {
+ type: 'selection',
+ width: 60,
+ align: 'center'
+ },
+ {
+ title: '妯℃澘鍚嶇О',
+ key: 'templateName',
+ align: 'center',
+ ellipsis: true,
+ tooltip: true
+ },
+ {
+ title: '鍚敤鐘舵��',
+ key: 'status',
+ width: 120,
+ align: 'center',
+ render: (h, params) => {
+ const status = params.row.status;
+ const color = status === 'ENABLE' ? 'success' : status === 'DISABLE' ? 'default' : 'warning';
+ const text = status === 'ENABLE' ? '鍚敤' : status === 'DISABLE' ? '鏈惎鐢�' : '鏈煡';
+
+ return h('Tag', {
+ props: {
+ color: color
+ }
+ }, text);
+ }
+ },
+ {
+ title: '鎿嶄綔',
+ slot: 'action',
+ width: 200,
+ align: 'center'
+ },
+ ]
+ }
+ },
+ methods: {
+ changeStatus(row){
+ changeStatus(row.id).then(res =>{
+ if (res.code ===200 ){
+ this.$Message.success(res.msg)
+ }
+ this.getList()
+ })
+
+ },
+ async updateTemplate(row){
+ this.showModal = true;
+ this.modalTitle = "淇敼妯℃澘";
+
+ await detail(row.id).then(res =>{
+ if (res.code === 200){
+ this.form = {
+ id: res.data.id,
+ templateName: res.data.templateName || '', // 纭繚涓嶄负undefined
+ titles: res.data.titles || [] // 鏍囬鍒楄〃
+ };
+ this.form.titles.map((i) =>{
+ i.id = null;
+ return i
+ })
+ this.listImages = res.data.listImages.map((i) => {
+ return i.imgUrl
+ });
+
+ }
+ })
+ const stsInfo = await getSts();
+ const endpoint = stsInfo.data.endpoint;
+ console.log()
+ this.showListImages = this.listImages.map((i) => {
+ if (i!=null&&i.indexOf('http')===-1)
+ return endpoint+'/'+i;
+ else return i;
+ })
+
+ },
+ delTemplate(row){
+ del(row.id).then(res =>{
+ if (res.code === 200){
+ this.$Message.success(res.msg)
+ }
+ this.getList()
+ })
+ },
+ async upLoadImg(file) {
+ console.log("鎵撳嵃涓婁紶1")
+ if (this.listImages.length >= 10) {
+ this.$Message.error("鍥剧墖涓婁紶涓嶈兘瓒呰繃10涓�");
+ return;
+ }
+ console.log("鎵撳嵃涓婁紶2")
+ try {
+ // 鑾峰彇鏂囦欢涓婁紶涓存椂瀵嗛挜
+ const sts = await getSts();
+ const cos = new COS({
+ getAuthorization: async function (options, callback) {
+ callback({
+ TmpSecretId: sts.data.tmpSecretId,
+ TmpSecretKey: sts.data.tmpSecretKey,
+ SecurityToken: sts.data.sessionToken,
+ // 寤鸿杩斿洖鏈嶅姟鍣ㄦ椂闂翠綔涓虹鍚嶇殑寮�濮嬫椂闂达紝閬垮厤瀹㈡埛绔湰鍦版椂闂村亸宸繃澶у鑷寸鍚嶉敊璇�
+ StartTime: sts.data.stsStartTime, // 鏃堕棿鎴筹紝鍗曚綅绉掞紝濡傦細1580000000
+ ExpiredTime: sts.data.stsEndTime,// 鏃堕棿鎴筹紝鍗曚綅绉掞紝濡傦細1580000000
+ ScopeLimit: true, // 缁嗙矑搴︽帶鍒舵潈闄愰渶瑕佽涓� true锛屼細闄愬埗瀵嗛挜鍙湪鐩稿悓璇锋眰鏃堕噸澶嶄娇鐢�
+ });
+ }
+ })
+ const fileKey = getFileKey(file.name)
+ const upData = await cos.uploadFile({
+ Bucket: sts.data.bucket,
+ Region: sts.data.region,
+ Key: fileKey,
+ Body: file, // 瑕佷笂浼犵殑鏂囦欢瀵硅薄銆�
+ SliceSize: 1024 * 1024 * 5,
+ onProgress: function (progressData) {
+ console.log('涓婁紶杩涘害锛�', progressData);
+ },
+ });
+ console.log("涓婁紶鎴愬姛", upData)
+ this.$nextTick(() => {
+ this.listImages.push(fileKey);
+ this.showListImages.push(sts.data.endpoint + "/" + fileKey);
+
+ })
+
+ } catch (e) {
+ console.log("涓婁紶澶辫触", upData)
+ return false;
+ } finally {
+
+ }
+ return false;
+ },
+ handleView(url) {
+ this.previewPicture = url;
+ this.visible = true;
+ },
+ handleRemove(item, index) {
+ if (!item) {
+ this.listImages.splice(index, 1);
+ this.showListImages.splice(index, 1);
+
+ } else {
+ console.log('绉婚櫎娴嬭瘯',item, index);
+ item.splice(index, 1)
+ }
+ this.previewPicture = "";
+ },
+
+ handleCLickImg(val, index) {
+ this.picModelFlag = true;
+ this.selectedFormBtnName = val;
+ },
+ handleViewGoodsPicture(url) {
+ this.previewGoodsPicture = url;
+ this.goodsPictureVisible = true;
+ },
+ // 绉婚櫎鍟嗗搧鍥剧墖
+ handleRemoveGoodsPicture(file) {
+ // this.baseInfoForm.goodsGalleryFiles =
+ // this.baseInfoForm.goodsGalleryFiles.filter((i) => i !== file);
+ },
+
+ addTitle(type){
+ this.form.titles.push(
+ {
+ contentType: type,
+ templateTitle: '',
+ imgTempUrl:null,//鍥剧墖涓存椂鍦板潃
+ file:null,
+ });
+ },
+ // 绉婚櫎鏍囬
+ removeTitle(index) {
+ this.form.titles.splice(index, 1);
+ },
+
+ saveOrUpdate() {
+ const submitData = {
+ ...this.form,
+ listImages: this.listImages,
+ };
+
+ console.log(submitData)
+
+ const isTitlesValid = (titles) => {
+ console.log("杩涘叆鍒ゆ柇")
+ // 鏁扮粍鏈韩涓簄ull/undefined鎴栫┖鏁扮粍
+ if (!titles || titles.length === 0) return false;
+ // 妫�鏌ユ瘡涓厓绱犵殑鏈夋晥鎬�
+ return titles.every(title => {
+ // 鍩虹鏍¢獙锛氬繀椤绘槸瀵硅薄涓斿寘鍚玞ontentType
+ if (!title || typeof title !== 'object' || !title.contentType) return false;
+
+ return title.templateTitle !== null
+ && title.templateTitle !== undefined
+ && title.templateTitle.trim() !== '';
+ // 鏈煡绫诲瀷
+ return false;
+ });
+ };
+
+ const isImagesValid = (images) => {
+ if (!images || images.length === 0) return false;
+ return images.some(img => img && (typeof img === 'string' ? img.trim() !== '' : true));
+ };
+
+ this.$refs.form.validate(async (valid) => {
+ if (valid) {
+ try {
+ // 鍏堝鐞嗘墍鏈夊浘鐗囦笂浼狅紙绛夊緟寮傛瀹屾垚锛�
+ this.submitLoading = true;
+
+ // 涓婁紶瀹屾垚鍚庡啀楠岃瘉
+ if (!isTitlesValid(submitData.titles)) {
+ this.$Message.error('璇风‘淇濇墍鏈夋爣棰橀兘濉啓瀹屾暣锛堟枃鏈爣棰樹笉鑳戒负绌猴紝鍥剧墖鏍囬闇�涓婁紶鎴愬姛锛�');
+ this.submitLoading = false;
+ return;
+ }
+
+ if (!isImagesValid(submitData.listImages)) {
+ this.$Message.error('璇锋坊鍔犳湁鏁堢殑鍥剧墖锛堣嚦灏戜竴寮犲浘鐗囷級');
+ this.submitLoading = false;
+ return;
+ }
+
+ // 楠岃瘉閫氳繃锛屾彁浜ゆ暟鎹�
+ const api = this.form.id ? edit : add;
+ const res = await api(submitData);
+
+ if (res.code === 200) {
+ this.$Message.success(res.msg);
+ this.modelShow = false;
+ this.getList();
+ } else {
+ this.$Message.error(res.msg);
+ }
+ } catch (error) {
+ this.$Message.error('鎻愪氦澶辫触锛岃閲嶈瘯');
+ console.error(error);
+ } finally {
+ this.submitLoading = false;
+ this.showModal = false;
+ }
+ }
+ });
+ },
+ addModal(){
+ this.form = {
+ titles: []
+ };
+ this.showModal = true;
+ this.modalTitle = "鏂板妯℃澘";
+ this.showListImages =[];
+ this.listImages =[];
+ },
+ detail(row){
+ console.log(row)
+ },
+
+ // 鑾峰彇鍒楄〃鏁版嵁
+ getList() {
+ this.listLoading = true;
+ // 妯℃嫙API璋冪敤
+ getPage(this.listQuery).then(res =>{
+ this.listLoading = false;
+ this.list = res.data;
+ this.total = res.total;
+ })
+ },
+
+ // 閲嶇疆鎼滅储鏉′欢
+ handleResetSearch() {
+ this.listQuery = {
+ pageNumber: 1,
+ pageSize: 10,
+ storeName: "",
+ couponName: "",
+ generateStatus: "",
+ status: ""
+ };
+ this.getList();
+ },
+
+ // 鍒嗛〉澶у皬鏀瑰彉
+ handleSizeChange(size) {
+ this.listQuery.pageSize = size;
+ this.listQuery.pageNumber = 1;
+ this.getList();
+ },
+
+ // 褰撳墠椤电爜鏀瑰彉
+ handleCurrentChange(pageNumber) {
+ this.listQuery.pageNumber = pageNumber;
+ this.getList();
+ },
+
+ // 鎻愪氦琛ㄥ崟
+ handleSubmit() {
+ this.$refs.dataForm.validate((valid) => {
+ if (valid) {
+ }
+ });
+ }
+ },
+ mounted() {
+ this.getList();
+ }
+}
+</script>
+
+<style scoped lang="less">
+.preview-image-limit{
+ max-width: 100%;
+ max-height: 200px;
+ object-fit: contain;
+ border-radius: 4px;
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+ display: block;
+}
+.delete-btn {
+ position: absolute; /* 缁濆瀹氫綅 */
+ top: 12px; /* 璺濈椤堕儴鐨勮窛绂� */
+ right: 12px; /* 璺濈鍙充晶鐨勮窛绂� */
+ padding: 4px 8px; /* 璋冩暣鎸夐挳澶у皬 */
+ line-height: 1; /* 璋冩暣琛岄珮 */
+}
+.title-item {
+ margin-bottom: 12px;
+ padding-bottom: 12px;
+ border-bottom: 1px dashed #e9e9e9;
+}
+
+.title-type-selector {
+ display: flex;
+ justify-content: center;
+ padding: 20px 0;
+}
+
+.type-option {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin: 0 20px;
+ cursor: pointer;
+ padding: 15px;
+ border-radius: 4px;
+ transition: all 0.3s;
+
+ &:hover {
+ background-color: #f5f7fa;
+ }
+
+ span {
+ margin-top: 10px;
+ }
+}
+.coupon-management {
+ padding: 16px;
+ background: #f5f7f9;
+ min-height: 100vh;
+}
+
+.filter-container {
+ margin-bottom: 16px;
+
+ .filter-header {
+ display: flex;
+ align-items: center;
+ margin-bottom: 16px;
+
+ .filter-title {
+ margin-left: 8px;
+ font-weight: 600;
+ font-size: 16px;
+ }
+
+ .filter-actions {
+ margin-left: auto;
+ }
+ }
+
+ .filter-content {
+ .search-form {
+ /deep/ .ivu-form-item {
+ margin-bottom: 16px;
+ margin-right: 16px;
+ }
+ }
+ }
+}
+
+.operation-container {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 16px;
+ padding: 12px 16px;
+ background: #fff;
+ border-radius: 4px;
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+
+ .operation-info {
+ color: #999;
+ font-size: 14px;
+ }
+}
+
+.table-container {
+ margin-bottom: 16px;
+
+ .coupon-table {
+ /deep/ .ivu-table-cell {
+ padding: 8px 12px;
+ }
+
+ .action-btns {
+ display: flex;
+ justify-content: center;
+
+ button {
+ margin: 0 2px;
+ }
+ }
+ }
+}
+
+.pagination-container {
+ display: flex;
+ justify-content: flex-end;
+ background: #fff;
+ padding: 12px 16px;
+ border-radius: 4px;
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+}
+
+// 鍝嶅簲寮忚皟鏁�
+@media (max-width: 768px) {
+ .coupon-management {
+ padding: 8px;
+ }
+
+ .filter-content .search-form {
+ /deep/ .ivu-form-item {
+ width: 100%;
+ margin-right: 0;
+
+ .ivu-form-item-content {
+ width: 100%;
+
+ .ivu-input, .ivu-select {
+ width: 100% !important;
+ }
+ }
+ }
+ }
+
+ .operation-container {
+ flex-direction: column;
+ align-items: flex-start;
+
+ .add-btn {
+ margin-bottom: 8px;
+ }
+ }
+
+ .action-btns {
+ flex-direction: column;
+
+ button {
+ margin: 2px 0 !important;
+ width: 100%;
+ }
+ }
+}
+.demo-upload-list {
+ display: inline-block;
+ width: 60px;
+ height: 60px;
+ text-align: center;
+ line-height: 60px;
+ border: 1px solid transparent;
+ border-radius: 4px;
+ overflow: hidden;
+ background: #fff;
+ position: relative;
+ box-shadow: 0 1px 1px rgba(0, 0, 0, .2);
+ margin-right: 4px;
+}
+
+.demo-upload-list img {
+ width: 100%;
+ height: 100%;
+}
+
+.demo-upload-list-cover {
+ display: none;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: rgba(0, 0, 0, .6);
+}
+
+.demo-upload-list:hover .demo-upload-list-cover {
+ display: block;
+}
+
+.demo-upload-list-cover i {
+ color: #fff;
+ font-size: 20px;
+ cursor: pointer;
+ margin: 0 2px;
+}
+</style>
--
Gitblit v1.8.0