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

@@ -19,132 +19,129 @@
</div>
</template>
<script>
<script setup>
import { onMounted, ref, watch } from "vue";
import AMapLoader from "@amap/amap-jsapi-loader";
import { getRegion } from "@/api/common.js";
import config from "@/config/index";
import { Message } from "@/utils/message";
export default {
name: "map",
data() {
return {
config,
showMap: false, // 地图显隐
mapSearch: "", // 地图搜索
map: null, // 初始化地图
autoComplete: null, // 初始化搜索方法
geocoder: null, // 初始化地理、坐标转化
positionPicker: null, // 地图拖拽选点
tips: [], //搜索关键字列表
addrContent: {}, // 回显地址信息
loading: false, // 加载状态
defineOptions({ name: "map" });
const emit = defineEmits(["getAddress"]);
const showMap = ref(false); // 地图显隐
const mapSearch = ref(""); // 地图搜索
const map = ref(null); // 初始化地图
const autoComplete = ref(null); // 初始化搜索方法
const geocoder = ref(null); // 初始化地理、坐标转化
const positionPicker = ref(null); // 地图拖拽选点
const tips = ref([]); //搜索关键字列表
const addrContent = ref({}); // 回显地址信息
const loading = ref(false); // 加载状态
watch(mapSearch, (val) => {
searchOfMap(val);
});
function ok() {
if (addrContent.value && addrContent.value.regeocode) {
const params = {
cityCode: addrContent.value.regeocode.addressComponent.citycode,
townName: addrContent.value.regeocode.addressComponent.township,
};
},
watch: {
mapSearch: function (val) {
this.searchOfMap(val);
},
},
methods: {
ok() {
getRegion(params).then((res) => {
if (res.success) {
addrContent.value.addr = res.result.name.replace(/,/g, " ");
addrContent.value.addrId = res.result.id;
loading.value = false;
if (this.addrContent && this.addrContent.regeocode) {
const params = {
cityCode: this.addrContent.regeocode.addressComponent.citycode,
townName: this.addrContent.regeocode.addressComponent.township,
};
getRegion(params).then((res) => {
if (res.success) {
this.addrContent.addr = res.result.name.replace(/,/g, " ");
this.addrContent.addrId = res.result.id;
this.loading = false;
this.$emit("getAddress", this.addrContent);
}
});
} else {
this.$Message.error('未获取到坐标信息!请查看高德API配置是否正确')
emit("getAddress", addrContent.value);
}
});
} else {
Message.error('未获取到坐标信息!请查看高德API配置是否正确')
}
}
function init() {
AMapLoader.load({
key: config.aMapKey, // 申请好的Web端开发者Key,首次调用 load 时必填
version: "", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [
"AMap.ToolBar",
"AMap.Autocomplete",
"AMap.PlaceSearch",
"AMap.Geolocation",
"AMap.Geocoder",
], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
AMapUI: {
// 是否加载 AMapUI,缺省不加载
version: "1.1", // AMapUI 缺省 1.1
plugins: ["misc/PositionPicker"], // 需要加载的 AMapUI ui插件
},
init() {
AMapLoader.load({
key: this.config.aMapKey, // 申请好的Web端开发者Key,首次调用 load 时必填
version: "", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [
"AMap.ToolBar",
"AMap.Autocomplete",
"AMap.PlaceSearch",
"AMap.Geolocation",
"AMap.Geocoder",
], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
AMapUI: {
// 是否加载 AMapUI,缺省不加载
version: "1.1", // AMapUI 缺省 1.1
plugins: ["misc/PositionPicker"], // 需要加载的 AMapUI ui插件
},
})
.then((AMap) => {
let that = this;
this.map = new AMap.Map("map-container", {
zoom: 12,
});
that.map.addControl(new AMap.ToolBar());
that.map.addControl(new AMap.Autocomplete());
that.map.addControl(new AMap.PlaceSearch());
that.map.addControl(new AMap.Geocoder());
// 实例化Autocomplete
let autoOptions = {
city: "全国",
};
that.autoComplete = new AMap.Autocomplete(autoOptions); // 搜索
that.geocoder = new AMap.Geocoder(autoOptions);
that.positionPicker = new AMapUI.PositionPicker({
// 拖拽选点
mode: "dragMap",
map: that.map,
});
that.positionPicker.start();
/**
*
* 所有回显数据,都在positionResult里面
* 需要字段可以查找
*
*/
that.positionPicker.on("success", function (positionResult) {
that.addrContent = positionResult;
});
})
.catch((e) => { });
},
searchOfMap(val) {
// 地图搜索
let that = this;
this.autoComplete.search(val, function (status, result) {
// 搜索成功时,result即是对应的匹配数据
if (status == "complete" && result.info == "OK") {
that.tips = result.tips;
} else {
that.tips = [];
}
})
.then((AMap) => {
map.value = new AMap.Map("map-container", {
zoom: 12,
});
},
selectAddr(location) {
// 选择坐标
if (!location) {
this.$Message.warning("请选择正确点位");
return false;
}
const lnglat = [location.lng, location.lat];
this.positionPicker.start(lnglat);
},
},
mounted() {
this.init();
},
};
map.value.addControl(new AMap.ToolBar());
map.value.addControl(new AMap.Autocomplete());
map.value.addControl(new AMap.PlaceSearch());
map.value.addControl(new AMap.Geocoder());
// 实例化Autocomplete
let autoOptions = {
city: "全国",
};
autoComplete.value = new AMap.Autocomplete(autoOptions); // 搜索
geocoder.value = new AMap.Geocoder(autoOptions);
positionPicker.value = new AMapUI.PositionPicker({
// 拖拽选点
mode: "dragMap",
map: map.value,
});
positionPicker.value.start();
/**
*
* 所有回显数据,都在positionResult里面
* 需要字段可以查找
*
*/
positionPicker.value.on("success", function (positionResult) {
addrContent.value = positionResult;
});
})
.catch((e) => { });
}
function searchOfMap(val) {
// 地图搜索
autoComplete.value.search(val, function (status, result) {
// 搜索成功时,result即是对应的匹配数据
if (status == "complete" && result.info == "OK") {
tips.value = result.tips;
} else {
tips.value = [];
}
});
}
function selectAddr(location) {
// 选择坐标
if (!location) {
Message.warning("请选择正确点位");
return false;
}
const lnglat = [location.lng, location.lat];
positionPicker.value.start(lnglat);
}
onMounted(() => {
init();
});
// 唯一引用方 multiple-map.vue 通过 ref 引用本组件但从不访问任何成员(仅监听 getAddress 事件),无需暴露成员
</script>
<style lang="scss" scoped>
#map-container {

View File

@@ -40,85 +40,87 @@
</el-dialog>
</template>
<script>
<script setup>
import { onMounted, reactive, ref } from "vue";
import { aMapSwitch } from "@/config/index";
import mapping from "@/components/map/index.vue";
import * as API_Setup from "@/api/common.js";
import { Message } from "@/utils/message";
export default {
components: { mapping },
data() {
return {
aMapSwitch,
enableMap: false,
mapDefault: "select",
data: {
province: [],
city: [],
area: [],
street: [],
},
chiosend: [],
};
},
mounted() {
this.chiosend = new Array(4).fill("");
},
methods: {
open() {
this.enableMap = true;
this.init({ id: 0 }, "province");
},
changeMap(val) {
this.mapDefault = val;
},
init(val, level = "province", index) {
if (level == 0) {
this.chiosend.splice(3, 1, val);
} else {
API_Setup.getChildRegion(val.id).then((res) => {
if (res.result.length && val.id !== 0) {
this.chiosend[index] = val;
} else if (!res.result.length) {
this.chiosend[index] = val;
}
this.data[level] = res.result;
if (level == "city") {
this.data.area = [];
this.data.street = [];
this.chiosend.splice(1, 3, "", "", "");
}
if (level == "area") {
this.data.street = [];
this.chiosend.splice(2, 2, "", "");
}
if (level == "street") {
this.chiosend.splice(3, 1, "");
}
});
const emit = defineEmits(["callback"]);
const enableMap = ref(false);
const mapDefault = ref("select");
const data = reactive({
province: [],
city: [],
area: [],
street: [],
});
const chiosend = ref([]);
// 模板 ref,对应高德地图子组件
const map = ref(null);
onMounted(() => {
chiosend.value = new Array(4).fill("");
});
function open() {
enableMap.value = true;
init({ id: 0 }, "province");
}
function changeMap(val) {
mapDefault.value = val;
}
function init(val, level = "province", index) {
if (level == 0) {
chiosend.value.splice(3, 1, val);
} else {
API_Setup.getChildRegion(val.id).then((res) => {
if (res.result.length && val.id !== 0) {
chiosend.value[index] = val;
} else if (!res.result.length) {
chiosend.value[index] = val;
}
},
getAddress(center) {
this.$emit("callback", {
type: this.mapDefault,
data: center,
});
this.enableMap = false;
},
finished() {
if (!this.chiosend[0]) {
this.$Message.error("请选择地址");
return;
data[level] = res.result;
if (level == "city") {
data.area = [];
data.street = [];
chiosend.value.splice(1, 3, "", "", "");
}
const params = this.chiosend.filter((item) => item !== "" && item.value !== "");
this.enableMap = false;
this.$emit("callback", {
type: this.mapDefault,
data: params,
});
},
},
};
if (level == "area") {
data.street = [];
chiosend.value.splice(2, 2, "", "");
}
if (level == "street") {
chiosend.value.splice(3, 1, "");
}
});
}
}
function getAddress(center) {
emit("callback", {
type: mapDefault.value,
data: center,
});
enableMap.value = false;
}
function finished() {
if (!chiosend.value[0]) {
Message.error("请选择地址");
return;
}
const params = chiosend.value.filter((item) => item !== "" && item.value !== "");
enableMap.value = false;
emit("callback", {
type: mapDefault.value,
data: params,
});
}
// 父组件(member/index、memberRecycle、memberDetail、orderDetail、shopOperation)通过 ref 调用 open() 打开弹窗
defineExpose({ open });
</script>
<style lang="scss" scoped>