123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693 |
- <template>
- <div class="discount-code-page">
- <!-- 头部导航 -->
- <s-header :name="$t('discountCode.discountCode')" :noback="false" />
- <!-- 主要内容区域 -->
- <!-- 顶部操作栏 -->
- <div class="top-action-bar" :class="{ 'delete-mode': isDelete }">
- <div class="status-display">
- <template v-if="isDelete">
- <span>{{ $t("advertManage.advertRule.selected") }}</span>
- <span class="count-highlight">{{ selectTotals }}</span>
- <span>{{ $t("advertManage.advertRule.individual") }}</span>
- </template>
- <template v-else>
- <span>{{ $t("discountCode.total") }}</span>
- <span class="count-highlight">{{ discountCodeTotal }}</span>
- <span>{{ $t("discountCode.discountCodesInTotal") }}</span>
- </template>
- </div>
- <div class="action-buttons">
- <template v-if="isDelete">
- <van-button
- size="small"
- class="action-button"
- @click="cancelClk"
- >
- {{ $t("discountCode.cancel") }}
- </van-button>
- <van-button
- size="small"
- type="primary"
- class="action-button"
- @click="allClk"
- >
- {{ $t("discountCode.selectAll") }}
- </van-button>
- <van-button
- size="small"
- type="danger"
- class="action-button"
- @click="noticeClk"
- >
- {{ $t("discountCode.confirmDel") }}
- </van-button>
- </template>
- <template v-else>
- <van-button
- icon="search"
- size="small"
- plain
- class="action-button"
- @click="searchClick"
- />
- <van-button
- icon="plus"
- type="primary"
- size="small"
- class="action-button"
- @click="payCode"
- >
- {{ $t("discountCode.apply") }}
- </van-button>
- <van-button
- icon="delete"
- size="small"
- type="danger"
- class="action-button"
- @click="isDelete = true"
- >
- {{ $t("discountCode.delete") }}
- </van-button>
- <van-button
- icon="down"
- size="small"
- type="success"
- class="action-button"
- @click="clickExport"
- >
- {{ $t("discountCode.export") }}
- </van-button>
- </template>
- </div>
- </div>
- <!-- 标签切换区域 -->
- <div class="tab-section">
- <div class="tab-buttons">
- <van-button
- size="small"
- :plain="isUse !== '0'"
- :type="isUse === '0' ? 'primary' : 'default'"
- @click="setIsUse('0')"
- >
- {{ $t("discountCode.notUsed") }}
- </van-button>
- <van-button
- size="small"
- :plain="isUse !== '1'"
- :type="isUse === '1' ? 'primary' : 'default'"
- @click="setIsUse('1')"
- >
- {{ $t("discountCode.used") }}
- </van-button>
- </div>
- </div>
- <div class="discount-code-list">
- <van-list
- v-model:loading="loading"
- v-model:error="error"
- :error-text="$t('public.requestFailed')"
- :finished="finished"
- :finished-text="$t('public.noMore')"
- :offset="300"
- :immediate-check="false"
- @load="onLoad"
- >
- <!-- 优惠码列表 -->
- <div
- v-for="(item, index) in discountCodeList"
- :key="index"
- class="code-card"
- :class="{
- used: item.isUse === '1',
- expired: isExpired(item.lastUseDate),
- }"
- @click="disCountCodeClick(item)"
- >
- <div class="code-header">
- <div class="code-value">
- <span class="code-label"
- >{{ $t("discountCode.discountCode") }}:</span
- >
- {{ item.code }}
- </div>
- </div>
- <div class="code-details">
- <!-- 创建时间 -->
- <div v-if="item.isUse === '0'" class="detail-row">
- <van-icon name="clock" class="detail-icon" />
- <div class="detail-content">
- <div class="detail-label">
- {{ $t("discountCode.creationTime") }}:
- </div>
- <div class="detail-value">
- {{ showDateTime(item.createDate) }}
- </div>
- </div>
- </div>
- <!-- 所属商户 -->
- <div v-if="user.type < 2" class="detail-row">
- <van-icon name="shop" class="detail-icon" />
- <div class="detail-content">
- <div class="detail-label">
- {{ $t("discountCode.affiliatedMerchants") }}:
- </div>
- <div class="detail-value">{{ item.userName || "-" }}</div>
- </div>
- </div>
- <!-- 使用时间 -->
- <div v-if="item.isUse !== '0'" class="detail-row">
- <van-icon name="todo-list" class="detail-icon" />
- <div class="detail-content">
- <div class="detail-label">
- {{ $t("discountCode.usageTime") }}:
- </div>
- <div class="detail-value">
- {{ showDateTime(item.useDate) }}
- </div>
- </div>
- </div>
- <!-- 有效期 -->
- <div v-if="item.isUse === '0'" class="detail-row">
- <van-icon name="todo-list" class="detail-icon" />
- <div class="detail-content">
- <div class="detail-label">
- {{ $t("discountCode.termOfValidity") }}:
- </div>
- <div class="detail-value">
- {{ showDate(item.lastUseDate) }}
- <van-tag
- v-if="isExpired(item.lastUseDate)"
- type="danger"
- size="small"
- >
- {{ $t("discountCode.expired") }}
- </van-tag>
- </div>
- </div>
- </div>
- <!-- 使用设备 -->
- <div v-if="item.isUse !== '0'" class="detail-row">
- <van-icon name="setting" class="detail-icon" />
- <div class="detail-content">
- <div class="detail-label">
- {{ $t("discountCode.usingTheMachine") }}:
- </div>
- <div class="detail-value">{{ item.useBy || "-" }}</div>
- </div>
- </div>
- </div>
- <!-- 状态标签 -->
- <div v-if="!isDelete" class="status-tag">
- <van-tag
- :type="item.type === '1' ? 'danger' : 'warning'"
- size="large"
- >
- {{
- item.type == "1"
- ? $t("discountCode.deduction")
- : $t("discountCode.discount")
- }}:
- {{ item.discount }}
- </van-tag>
- <van-tag v-if="item.isUse === '0'" type="primary" size="large">
- {{ $t("discountCode.notUsed") }}
- </van-tag>
- <van-tag v-else-if="item.isUse === '1'" type="success" size="large">
- {{ $t("discountCode.used") }}
- </van-tag>
- </div>
- <!-- 删除模式下的选择框 -->
- <van-checkbox
- v-if="isDelete"
- v-model="item.checked"
- class="selection-checkbox"
- @click.stop
- />
- </div>
- </van-list>
- </div>
- <!-- 搜索弹出框 -->
- <codeSearch ref="searchRef" @search="search($event)"></codeSearch>
- <!-- 导出功能 -->
- <codeExport ref="exportRef" @exportCode="exportCode($event)"></codeExport>
- </div>
- </template>
- <script>
- import { onMounted, reactive, toRefs, ref, computed } from "vue";
- import sHeader from "@/components/SimpleHeader";
- import {
- getdiscountCodeList,
- discountCodeExport,
- deleteCode,
- } from "@/service/discountCode";
- import { showFailToast, showToast, showConfirmDialog } from "vant";
- import { getLoginUser, $M_ExportFile } from "@/common/js/utils";
- import codeSearch from "./codeSearch.vue";
- import codeExport from "./codeExport.vue";
- import dateUtil from "@/utils/dateUtil";
- import { useRouter } from "vue-router";
- import { useI18n } from "vue-i18n";
- export default {
- setup() {
- const { t } = useI18n();
- const router = useRouter();
- const searchRef = ref(null);
- const exportRef = ref(null);
- const user = getLoginUser();
- const loading = ref(false); // 加载状态
- const error = ref(false); // 错误状态
- const finished = ref(false); // 结束翻页状态
- const discountCodeList = ref([]); // 列表集合
- const discountCodeTotal = ref(0); // 列表总数
- let searchParams = reactive({
- adminId: "", // 用户账户id
- current: 1, // 页数
- size: 20, // 页大小
- isUse: "0", // 是否使用,0:未使用;1:已使用
- // type: null // 优惠码类型 0或null:折扣优惠码;1:抵扣价优惠码
- });
- // 初始化页面获取列表
- onMounted(async () => {
- //加载样式
- // 初始化列表及页码
- const user = getLoginUser();
- if (user) {
- searchParams.adminId = user.id;
- searchGetList();
- }
- });
- // 搜索弹窗触发搜索
- const search = (data) => {
- searchParams = Object.assign(searchParams, data);
- searchGetList();
- };
- // 导出弹窗触发导出
- const exportCode = (data) => {
- searchParams = Object.assign(searchParams, data);
- exportClick();
- };
- // 查询列表
- const searchGetList = () => {
- discountCodeList.value = [];
- searchParams.current = 1;
- getList();
- };
- // 滚动加载
- const onLoad = () => {
- if (!finished.value) {
- searchParams.current = searchParams.current + 1;
- getList();
- }
- };
- // 获取设备列表数据
- const getList = async () => {
- const { data } = await getdiscountCodeList(
- Object.assign({}, searchParams)
- );
- if (data.code === "00000") {
- // 加入删除选中状态
- if (data.data.records.length > 0) {
- data.data.records.forEach((item) => {
- item.checked = false;
- });
- }
- // 列表值叠加
- discountCodeList.value = discountCodeList.value.concat(
- data.data.records
- );
- // console.log(discountCodeList.value);
- discountCodeTotal.value = data.data.total;
- if (discountCodeList.value.length === data.data.total) {
- finished.value = true;
- }
- loading.value = false;
- } else {
- showFailToast(data.message);
- }
- };
- // 搜索点击
- const searchClick = () => {
- searchRef.value.showSearch();
- };
- // 导出点击
- const clickExport = () => {
- exportRef.value.showExport();
- };
- // 切换tab
- const setIsUse = (data) => {
- searchParams.isUse = data;
- searchGetList();
- };
- // 点击优惠码
- const disCountCodeClick = (data) => {
- console.log("disCountCodeClick", data);
- };
- // 时间格式化
- const showDate = (date) => {
- return date ? dateUtil.formateDate(new Date(date), "yyyy/MM/dd") : "";
- };
- const showDateTime = (date) => {
- return date
- ? dateUtil.formateDate(new Date(date), "yyyy/MM/dd hh:mm:ss")
- : "";
- };
- // 优惠码导出
- const exportClick = async () => {
- searchParams.size = 3000;
- const { headers, data } = await discountCodeExport(
- Object.assign({}, searchParams)
- );
- $M_ExportFile(data, headers);
- };
- const payCode = () => {
- router.push({ path: "/payCode" });
- };
- const isExpired = ref((lastUseDate) => {
- const currentDate = new Date();
- const lastUseDateTime = new Date(lastUseDate);
- return currentDate > lastUseDateTime;
- });
- // 是否删除状态
- const isDelete = ref(false); // 选中
- const selectTotals = computed(() => {
- let nums = 0;
- if (discountCodeList.value.length > 0) {
- discountCodeList.value.forEach((item) => {
- if (item.checked) {
- nums++;
- }
- });
- }
- return nums;
- });
- const cancelClk = () => {
- // 把选中状态去掉
- if (discountCodeList.value.length > 0) {
- discountCodeList.value.forEach((item) => {
- if (item.checked) {
- item.checked = false;
- }
- });
- }
- isDelete.value = false;
- };
- // 点击全选
- const allClk = () => {
- if (discountCodeList.value.length > 0) {
- discountCodeList.value.forEach((item) => {
- item.checked = true;
- });
- }
- };
- // 点击确认删除
- const noticeClk = () => {
- if (selectTotals.value < 1) {
- showToast(t("advertManage.delTips"));
- return;
- }
- showConfirmDialog({
- title: t("advertManage.delPopTitle"),
- message: t("advertManage.delPopContent"),
- })
- .then(() => {
- const ids = [];
- discountCodeList.value.forEach((item) => {
- if (item.checked) {
- ids.push(item.id);
- }
- });
- deleteCode(ids)
- .then((res) => {
- console.log(res);
- if (res.data.code === "00000") {
- isDelete.value = false;
- showToast(t("discountCode.deletionSucceeded"));
- setTimeout(() => {
- discountCodeList.value = [];
- getList();
- }, 1500);
- }
- })
- .catch(() => {
- isDelete.value = false;
- showToast("ERROR");
- });
- })
- .catch(() => {
- // showToast('ERROR');
- });
- };
- return {
- searchRef,
- exportRef,
- loading,
- error,
- finished,
- discountCodeList,
- discountCodeTotal,
- ...toRefs(searchParams),
- onLoad,
- searchClick,
- search,
- setIsUse,
- disCountCodeClick,
- showDate,
- showDateTime,
- // exportClick,
- payCode,
- isExpired,
- isDelete,
- allClk,
- noticeClk,
- selectTotals,
- cancelClk,
- user,
- clickExport,
- exportCode,
- };
- },
- components: { sHeader, codeSearch, codeExport },
- };
- </script>
- <style lang="less" scoped>
- @primary-color: #4d6add;
- @error-color: #ff4d4f;
- .discount-code-page {
- display: flex;
- flex-direction: column;
- height: 100vh;
- background-color: #f5f7fa;
- }
- .top-action-bar {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 15px;
- margin: 12px;
- background-color: white;
- border-radius: 12px;
- box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
- &.delete-mode {
- background-color: #fff8f6;
- border-left: 4px solid @error-color;
- }
- .status-display {
- font-size: 14px;
- color: #666;
- .count-highlight {
- font-weight: bold;
- font-size: 16px;
- color: @primary-color;
- margin: 0 4px;
- }
- }
- .action-buttons {
- display: flex;
- gap: 8px;
- }
- .action-button {
- min-width: auto;
- padding: 5px 10px;
- }
- }
- .tab-section {
- background-color: white;
- border-radius: 12px;
- box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
- padding: 15px;
- margin: 12px;
- .tab-buttons {
- display: flex;
- gap: 12px;
- .van-button {
- flex: 1;
- }
- }
- }
- .discount-code-list {
- flex: 1;
- overflow-y: auto;
- }
- .code-card {
- background-color: white;
- border-radius: 12px;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
- padding: 16px;
- position: relative;
- overflow: hidden;
- transition: all 0.3s;
- margin: 12px;
- &:hover {
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
- transform: translateY(-2px);
- }
- &.used {
- background-color: #f6ffed;
- }
- &.expired {
- border-left: 4px solid @error-color;
- opacity: 0.8;
- }
- .code-header {
- display: flex;
- // justify-content: space-between;
- gap: 10px;
- align-items: center;
- padding-bottom: 12px;
- margin-bottom: 12px;
- border-bottom: 1px dashed #f0f0f0;
- }
- .code-value {
- font-size: 16px;
- font-weight: bold;
- color: #333;
- .code-label {
- font-weight: normal;
- color: #666;
- margin-right: 8px;
- }
- }
- .code-type {
- .van-tag {
- border-radius: 4px;
- font-weight: 500;
- }
- }
- .code-details {
- .detail-row {
- display: flex;
- margin-bottom: 10px;
- align-items: flex-start;
- &:last-child {
- margin-bottom: 0;
- }
- }
- .detail-icon {
- font-size: 16px;
- color: #999;
- margin-right: 10px;
- margin-top: 3px;
- min-width: 16px;
- }
- .detail-content {
- flex: 1;
- }
- .detail-label {
- font-size: 13px;
- color: #999;
- margin-bottom: 2px;
- }
- .detail-value {
- font-size: 14px;
- color: #333;
- line-height: 1.4;
- }
- }
- .status-tag {
- display: flex;
- gap: 5px;
- position: absolute;
- top: 10px;
- right: 10px;
- z-index: 2;
- }
- .selection-checkbox {
- position: absolute;
- bottom: 10px;
- right: 10px;
- z-index: 2;
- }
- }
- @media (max-width: 480px) {
- .top-action-bar {
- padding: 12px;
- flex-direction: column;
- align-items: stretch;
- gap: 12px;
- .action-buttons {
- justify-content: space-between;
- }
- }
- .code-card {
- padding: 12px;
- .code-value {
- font-size: 15px;
- }
- .status-tag .van-tag {
- font-size: 12px;
- padding: 2px 6px;
- }
- }
- }
- </style>
|