refactor: 四端完成 Options API → script setup + vuex → pinia 迁移

- buyer(95) / seller(169) / im(53) / manager(280) 共 597 个组件全部从 Options API 转换为 <script setup>
- 四端 vuex 全部移除,状态管理统一迁移至 pinia 4(stores/ 目录)
- util.js 等基础设施去除 vm 首参依赖;全局属性($Message/$filters 等)在 script 内改为具名导入
- 被外部 ref 访问的公共组件均已补齐 defineExpose(清单见各端 MIGRATION-VUE3.md)
- 各端 eslint 启用 vue/component-api-style 防止新代码回退 Options API
- 四端 yarn build 全部通过;迁移约定与注意事项已更新至各端 MIGRATION-VUE3.md
This commit is contained in:
lifenlong
2026-10-13 07:06:59 +08:00
parent 870bacdd8c
commit 88fc1b0b2a
674 changed files with 71220 additions and 69943 deletions

View File

@@ -31,45 +31,43 @@
</div>
</template>
<script>
<script setup>
import { ref, onMounted } from "vue";
import { getWxChannelsThirdCategory } from "@/api/index";
export default {
name: "WxChannelsCategoryTab",
data() {
return {
forceRefresh: false,
loading: false,
data: [],
};
},
mounted() {
this.loadThirdCategories();
},
methods: {
qualificationLabel(val) {
const map = { 0: "不需要", 1: "必填", 2: "选填" };
return map[val] || "-";
},
qualificationTagType(val) {
if (val === 1) return "danger";
if (val === 2) return "warning";
return "success";
},
loadThirdCategories() {
this.loading = true;
getWxChannelsThirdCategory({ forceRefresh: !!this.forceRefresh })
.then((res) => {
if (res && res.success) {
this.data = Array.isArray(res.result) ? res.result : [];
}
})
.finally(() => {
this.loading = false;
});
},
},
};
defineOptions({ name: "WxChannelsCategoryTab" });
const forceRefresh = ref(false);
const loading = ref(false);
const data = ref([]);
function qualificationLabel(val) {
const map = { 0: "不需要", 1: "必填", 2: "选填" };
return map[val] || "-";
}
function qualificationTagType(val) {
if (val === 1) return "danger";
if (val === 2) return "warning";
return "success";
}
function loadThirdCategories() {
loading.value = true;
getWxChannelsThirdCategory({ forceRefresh: !!forceRefresh.value })
.then((res) => {
if (res && res.success) {
data.value = Array.isArray(res.result) ? res.result : [];
}
})
.finally(() => {
loading.value = false;
});
}
onMounted(() => {
loadThirdCategories();
});
</script>
<style scoped lang="scss">

View File

@@ -58,68 +58,64 @@
</div>
</template>
<script>
<script setup>
import { onMounted, reactive, ref } from "vue";
import { getWxChannelsGoodsPage } from "@/api/index";
export default {
name: "WxChannelsGoodsTab",
data() {
return {
statusList: [
{ label: "已通过", value: "APPROVED" },
{ label: "审核中", value: "PENDING" },
{ label: "已拒绝", value: "REJECTED" },
],
loading: false,
total: 0,
data: [],
searchForm: {
goodsName: "",
status: "",
pageNumber: 1,
pageSize: 20,
},
};
},
mounted() {
this.loadPage();
},
methods: {
statusLabel(val) {
const map = { APPROVED: "已通过", PENDING: "审核中", REJECTED: "已拒绝" };
return map[val] || val || "-";
},
statusTagType(val) {
const map = { APPROVED: "success", PENDING: "warning", REJECTED: "danger" };
return map[val] || "info";
},
handleSearch() {
this.searchForm.pageNumber = 1;
this.loadPage();
},
changePage(pageNumber) {
this.searchForm.pageNumber = pageNumber;
this.loadPage();
},
changePageSize(pageSize) {
this.searchForm.pageSize = pageSize;
this.searchForm.pageNumber = 1;
this.loadPage();
},
loadPage() {
this.loading = true;
getWxChannelsGoodsPage({ ...this.searchForm })
.then((res) => {
if (res && res.success) {
const page = res.result || {};
this.data = Array.isArray(page.records) ? page.records : [];
this.total = Number(page.total || 0);
}
})
.finally(() => {
this.loading = false;
});
},
},
};
defineOptions({ name: "WxChannelsGoodsTab" });
const statusList = ref([
{ label: "已通过", value: "APPROVED" },
{ label: "审核中", value: "PENDING" },
{ label: "已拒绝", value: "REJECTED" },
]);
const loading = ref(false);
const total = ref(0);
const data = ref([]);
const searchForm = reactive({
goodsName: "",
status: "",
pageNumber: 1,
pageSize: 20,
});
function statusLabel(val) {
const map = { APPROVED: "已通过", PENDING: "审核中", REJECTED: "已拒绝" };
return map[val] || val || "-";
}
function statusTagType(val) {
const map = { APPROVED: "success", PENDING: "warning", REJECTED: "danger" };
return map[val] || "info";
}
function handleSearch() {
searchForm.pageNumber = 1;
loadPage();
}
function changePage(pageNumber) {
searchForm.pageNumber = pageNumber;
loadPage();
}
function changePageSize(pageSize) {
searchForm.pageSize = pageSize;
searchForm.pageNumber = 1;
loadPage();
}
function loadPage() {
loading.value = true;
getWxChannelsGoodsPage({ ...searchForm })
.then((res) => {
if (res && res.success) {
const page = res.result || {};
data.value = Array.isArray(page.records) ? page.records : [];
total.value = Number(page.total || 0);
}
})
.finally(() => {
loading.value = false;
});
}
onMounted(() => {
loadPage();
});
</script>

View File

@@ -70,88 +70,84 @@
</div>
</template>
<script>
<script setup>
import { onMounted, reactive, ref } from "vue";
import { getWxChannelsOrderPage } from "@/api/index";
export default {
name: "WxChannelsOrderTab",
data() {
return {
sceneList: [
{ label: "直播", value: "LIVE" },
{ label: "橱窗", value: "WINDOW" },
],
loading: false,
total: 0,
data: [],
selectDate: null,
searchForm: {
channelOrderSn: "",
memberNickName: "",
goodsName: "",
status: "",
scene: "",
startTime: null,
endTime: null,
pageNumber: 1,
pageSize: 20,
},
};
},
mounted() {
this.loadPage();
},
methods: {
sceneLabel(val) {
const map = { LIVE: "直播", WINDOW: "橱窗" };
return map[val] || val || "-";
},
sceneTagType(val) {
const map = { LIVE: "warning", WINDOW: "" };
return map[val] || "info";
},
selectDateRange(v) {
if (!v || v.length !== 2) {
this.searchForm.startTime = null;
this.searchForm.endTime = null;
return;
defineOptions({ name: "WxChannelsOrderTab" });
const sceneList = ref([
{ label: "直播", value: "LIVE" },
{ label: "橱窗", value: "WINDOW" },
]);
const loading = ref(false);
const total = ref(0);
const data = ref([]);
const selectDate = ref(null);
const searchForm = reactive({
channelOrderSn: "",
memberNickName: "",
goodsName: "",
status: "",
scene: "",
startTime: null,
endTime: null,
pageNumber: 1,
pageSize: 20,
});
onMounted(() => {
loadPage();
});
function sceneLabel(val) {
const map = { LIVE: "直播", WINDOW: "橱窗" };
return map[val] || val || "-";
}
function sceneTagType(val) {
const map = { LIVE: "warning", WINDOW: "" };
return map[val] || "info";
}
function selectDateRange(v) {
if (!v || v.length !== 2) {
searchForm.startTime = null;
searchForm.endTime = null;
return;
}
const start = v[0] ? new Date(`${v[0]}T00:00:00`).getTime() : null;
const end = v[1] ? new Date(`${v[1]}T23:59:59`).getTime() : null;
searchForm.startTime = Number.isFinite(start) ? start : null;
searchForm.endTime = Number.isFinite(end) ? end : null;
}
function handleSearch() {
searchForm.pageNumber = 1;
loadPage();
}
function changePage(pageNumber) {
searchForm.pageNumber = pageNumber;
loadPage();
}
function changePageSize(pageSize) {
searchForm.pageSize = pageSize;
searchForm.pageNumber = 1;
loadPage();
}
function loadPage() {
loading.value = true;
const params = { ...searchForm };
Object.keys(params).forEach((k) => {
if (params[k] === null || params[k] === "" || params[k] === undefined) delete params[k];
});
getWxChannelsOrderPage(params)
.then((res) => {
if (res && res.success) {
const page = res.result || {};
data.value = Array.isArray(page.records) ? page.records : [];
total.value = Number(page.total || 0);
}
const start = v[0] ? new Date(`${v[0]}T00:00:00`).getTime() : null;
const end = v[1] ? new Date(`${v[1]}T23:59:59`).getTime() : null;
this.searchForm.startTime = Number.isFinite(start) ? start : null;
this.searchForm.endTime = Number.isFinite(end) ? end : null;
},
handleSearch() {
this.searchForm.pageNumber = 1;
this.loadPage();
},
changePage(pageNumber) {
this.searchForm.pageNumber = pageNumber;
this.loadPage();
},
changePageSize(pageSize) {
this.searchForm.pageSize = pageSize;
this.searchForm.pageNumber = 1;
this.loadPage();
},
loadPage() {
this.loading = true;
const params = { ...this.searchForm };
Object.keys(params).forEach((k) => {
if (params[k] === null || params[k] === "" || params[k] === undefined) delete params[k];
});
getWxChannelsOrderPage(params)
.then((res) => {
if (res && res.success) {
const page = res.result || {};
this.data = Array.isArray(page.records) ? page.records : [];
this.total = Number(page.total || 0);
}
})
.finally(() => {
this.loading = false;
});
},
},
};
})
.finally(() => {
loading.value = false;
});
}
</script>

View File

@@ -74,66 +74,64 @@
</div>
</template>
<script>
<script setup>
import { onMounted, reactive, ref } from "vue";
import { getWxChannelsOverviewSummary } from "@/api/index";
export default {
name: "WxChannelsOverviewTab",
data() {
return {
loading: false,
selectDate: null,
searchForm: {
startTime: null,
endTime: null,
},
summary: {
totalSales: 0,
liveSales: 0,
windowSales: 0,
totalRefund: 0,
liveRefund: 0,
windowRefund: 0,
},
};
},
mounted() {
this.loadSummary();
},
methods: {
selectDateRange(v) {
if (!v || v.length !== 2) {
this.searchForm.startTime = null;
this.searchForm.endTime = null;
return;
defineOptions({ name: "WxChannelsOverviewTab" });
const loading = ref(false);
const selectDate = ref(null);
const searchForm = reactive({
startTime: null,
endTime: null,
});
const summary = reactive({
totalSales: 0,
liveSales: 0,
windowSales: 0,
totalRefund: 0,
liveRefund: 0,
windowRefund: 0,
});
onMounted(() => {
loadSummary();
});
function selectDateRange(v) {
if (!v || v.length !== 2) {
searchForm.startTime = null;
searchForm.endTime = null;
return;
}
const [startStr, endStr] = v;
const start = startStr ? new Date(`${startStr}T00:00:00`).getTime() : null;
const end = endStr ? new Date(`${endStr}T23:59:59`).getTime() : null;
searchForm.startTime = Number.isFinite(start) ? start : null;
searchForm.endTime = Number.isFinite(end) ? end : null;
}
function handleSearch() {
loadSummary();
}
function loadSummary() {
loading.value = true;
const params = { ...searchForm };
Object.keys(params).forEach((k) => {
if (params[k] === null || params[k] === "" || params[k] === undefined) delete params[k];
});
getWxChannelsOverviewSummary(params)
.then((res) => {
if (res && res.success) {
Object.assign(summary, res.result || {});
}
const [startStr, endStr] = v;
const start = startStr ? new Date(`${startStr}T00:00:00`).getTime() : null;
const end = endStr ? new Date(`${endStr}T23:59:59`).getTime() : null;
this.searchForm.startTime = Number.isFinite(start) ? start : null;
this.searchForm.endTime = Number.isFinite(end) ? end : null;
},
handleSearch() {
this.loadSummary();
},
loadSummary() {
this.loading = true;
const params = { ...this.searchForm };
Object.keys(params).forEach((k) => {
if (params[k] === null || params[k] === "" || params[k] === undefined) delete params[k];
});
getWxChannelsOverviewSummary(params)
.then((res) => {
if (res && res.success) {
this.summary = { ...this.summary, ...(res.result || {}) };
}
})
.finally(() => {
this.loading = false;
});
},
},
};
})
.finally(() => {
loading.value = false;
});
}
</script>
<style scoped lang="scss">

View File

@@ -72,89 +72,85 @@
</div>
</template>
<script>
<script setup>
import { onMounted, reactive, ref } from "vue";
import { getWxChannelsRefundPage } from "@/api/index";
export default {
name: "WxChannelsRefundTab",
data() {
return {
sceneList: [
{ label: "直播", value: "LIVE" },
{ label: "橱窗", value: "WINDOW" },
],
loading: false,
total: 0,
data: [],
selectDate: null,
searchForm: {
channelRefundSn: "",
channelOrderSn: "",
memberNickName: "",
goodsName: "",
status: "",
scene: "",
startTime: null,
endTime: null,
pageNumber: 1,
pageSize: 20,
},
};
},
mounted() {
this.loadPage();
},
methods: {
sceneLabel(val) {
const map = { LIVE: "直播", WINDOW: "橱窗" };
return map[val] || val || "-";
},
sceneTagType(val) {
const map = { LIVE: "warning", WINDOW: "" };
return map[val] || "info";
},
selectDateRange(v) {
if (!v || v.length !== 2) {
this.searchForm.startTime = null;
this.searchForm.endTime = null;
return;
defineOptions({ name: "WxChannelsRefundTab" });
const sceneList = ref([
{ label: "直播", value: "LIVE" },
{ label: "橱窗", value: "WINDOW" },
]);
const loading = ref(false);
const total = ref(0);
const data = ref([]);
const selectDate = ref(null);
const searchForm = reactive({
channelRefundSn: "",
channelOrderSn: "",
memberNickName: "",
goodsName: "",
status: "",
scene: "",
startTime: null,
endTime: null,
pageNumber: 1,
pageSize: 20,
});
onMounted(() => {
loadPage();
});
function sceneLabel(val) {
const map = { LIVE: "直播", WINDOW: "橱窗" };
return map[val] || val || "-";
}
function sceneTagType(val) {
const map = { LIVE: "warning", WINDOW: "" };
return map[val] || "info";
}
function selectDateRange(v) {
if (!v || v.length !== 2) {
searchForm.startTime = null;
searchForm.endTime = null;
return;
}
const start = v[0] ? new Date(`${v[0]}T00:00:00`).getTime() : null;
const end = v[1] ? new Date(`${v[1]}T23:59:59`).getTime() : null;
searchForm.startTime = Number.isFinite(start) ? start : null;
searchForm.endTime = Number.isFinite(end) ? end : null;
}
function handleSearch() {
searchForm.pageNumber = 1;
loadPage();
}
function changePage(pageNumber) {
searchForm.pageNumber = pageNumber;
loadPage();
}
function changePageSize(pageSize) {
searchForm.pageSize = pageSize;
searchForm.pageNumber = 1;
loadPage();
}
function loadPage() {
loading.value = true;
const params = { ...searchForm };
Object.keys(params).forEach((k) => {
if (params[k] === null || params[k] === "" || params[k] === undefined) delete params[k];
});
getWxChannelsRefundPage(params)
.then((res) => {
if (res && res.success) {
const page = res.result || {};
data.value = Array.isArray(page.records) ? page.records : [];
total.value = Number(page.total || 0);
}
const start = v[0] ? new Date(`${v[0]}T00:00:00`).getTime() : null;
const end = v[1] ? new Date(`${v[1]}T23:59:59`).getTime() : null;
this.searchForm.startTime = Number.isFinite(start) ? start : null;
this.searchForm.endTime = Number.isFinite(end) ? end : null;
},
handleSearch() {
this.searchForm.pageNumber = 1;
this.loadPage();
},
changePage(pageNumber) {
this.searchForm.pageNumber = pageNumber;
this.loadPage();
},
changePageSize(pageSize) {
this.searchForm.pageSize = pageSize;
this.searchForm.pageNumber = 1;
this.loadPage();
},
loadPage() {
this.loading = true;
const params = { ...this.searchForm };
Object.keys(params).forEach((k) => {
if (params[k] === null || params[k] === "" || params[k] === undefined) delete params[k];
});
getWxChannelsRefundPage(params)
.then((res) => {
if (res && res.success) {
const page = res.result || {};
this.data = Array.isArray(page.records) ? page.records : [];
this.total = Number(page.total || 0);
}
})
.finally(() => {
this.loading = false;
});
},
},
};
})
.finally(() => {
loading.value = false;
});
}
</script>

View File

@@ -28,8 +28,12 @@
</div>
</template>
<script>
<script setup>
import { onMounted, ref } from "vue";
import { getSetting, setSetting } from "@/api/index";
import { Message } from "@/utils/message";
defineOptions({ name: "WxChannelsSettingTab" });
const defaultConfig = () => ({
appId: "",
@@ -38,71 +42,67 @@ const defaultConfig = () => ({
tokenUrl: "",
});
export default {
name: "WxChannelsSettingTab",
data() {
return {
loading: false,
submitLoading: false,
configObject: defaultConfig(),
};
},
mounted() {
this.reloadConfig();
},
methods: {
normalizeConfig(val) {
if (!val) return {};
if (typeof val === "string") {
try {
return JSON.parse(val);
} catch (e) {
return {};
}
}
if (typeof val === "object") return val;
const loading = ref(false);
const submitLoading = ref(false);
const configObject = ref(defaultConfig());
function normalizeConfig(val) {
if (!val) return {};
if (typeof val === "string") {
try {
return JSON.parse(val);
} catch (e) {
return {};
},
pickConfigFields(val) {
const next = defaultConfig();
if (!val || typeof val !== "object") return next;
Object.keys(next).forEach((k) => {
if (val[k] !== undefined && val[k] !== null) {
next[k] = val[k];
}
});
return next;
},
reloadConfig() {
this.loading = true;
getSetting("WX_CHANNELS")
.then((res) => {
if (res && res.success) {
const raw = this.normalizeConfig(res.result);
this.configObject = this.pickConfigFields(raw);
}
})
.finally(() => {
this.loading = false;
});
},
submit() {
this.submitLoading = true;
setSetting("WX_CHANNELS", this.configObject)
.then((res) => {
if (res && res.success) {
this.$Message.success("保存成功");
this.reloadConfig();
} else {
this.$Message.error("保存失败");
}
})
.finally(() => {
this.submitLoading = false;
});
},
},
};
}
}
if (typeof val === "object") return val;
return {};
}
function pickConfigFields(val) {
const next = defaultConfig();
if (!val || typeof val !== "object") return next;
Object.keys(next).forEach((k) => {
if (val[k] !== undefined && val[k] !== null) {
next[k] = val[k];
}
});
return next;
}
function reloadConfig() {
loading.value = true;
getSetting("WX_CHANNELS")
.then((res) => {
if (res && res.success) {
const raw = normalizeConfig(res.result);
configObject.value = pickConfigFields(raw);
}
})
.finally(() => {
loading.value = false;
});
}
function submit() {
submitLoading.value = true;
setSetting("WX_CHANNELS", configObject.value)
.then((res) => {
if (res && res.success) {
Message.success("保存成功");
reloadConfig();
} else {
Message.error("保存失败");
}
})
.finally(() => {
submitLoading.value = false;
});
}
onMounted(() => {
reloadConfig();
});
</script>
<style scoped lang="scss">

View File

@@ -23,7 +23,8 @@
</el-card>
</template>
<script>
<script setup>
import { ref } from "vue";
import WxChannelsSettingTab from "./components/WxChannelsSettingTab.vue";
import WxChannelsCategoryTab from "./components/WxChannelsCategoryTab.vue";
import WxChannelsGoodsTab from "./components/WxChannelsGoodsTab.vue";
@@ -31,20 +32,7 @@ import WxChannelsOrderTab from "./components/WxChannelsOrderTab.vue";
import WxChannelsOverviewTab from "./components/WxChannelsOverviewTab.vue";
import WxChannelsRefundTab from "./components/WxChannelsRefundTab.vue";
export default {
name: "wx-channel",
components: {
WxChannelsSettingTab,
WxChannelsCategoryTab,
WxChannelsGoodsTab,
WxChannelsOrderTab,
WxChannelsOverviewTab,
WxChannelsRefundTab,
},
data() {
return {
selectedTab: "WX_CHANNELS",
};
},
};
defineOptions({ name: "wx-channel" });
const selectedTab = ref("WX_CHANNELS");
</script>